Pagination problem in homepageDetail viewer

9 posts by 2 authors in: Forums > CMS Builder
Last Post: December 3, 2013   (RSS)

By Dave - November 28, 2013

Hi Tom, 

The default detail viewer page code looks for the last number in the URL.  So you need to either change that to use a named variable, eg: ?num=6, or change your code so the generated links maintain the number on the end of the URL.

Try replacing this: 

<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => '1' ))) ?>

With either this (our function): 

<?php echo thisPageUrl(array('page'=>1)); ?>

or this (reversed order of array elements): 

<?php echo http_build_query(array_merge(array( 'page' => '1' ), $_REQUEST)) ?>

Let me know if that works for you or any questions.  Thanks!

Dave Edis - Senior Developer
interactivetools.com

By Tom - November 29, 2013 - edited: November 29, 2013

Hi Dave,

Thanks for your reply,

However, I did follow your instruction to replace the line.

Unluckily, the number after the url still becomes ZERO.

The correct URL should be xxx.com/agent.html?2&page=2

But it becomes xxx.com/agent.html?0&page=2

And I have made a test on some other viewer

For example in the listings.php

The normal url xxx.com/listings.php?cat=abc&page=2

If I replace the cat=     to a number

e.g.

xxx.com/listings.php?123=abc&page=2

The 123 will become ZERO as well

xxx.com/listings.php?0=abc&page=2

Please advice.

Thanks

By Dave - December 2, 2013

Hi Tom, 

Can you try using our function? 

<?php echo thisPageUrl(array('page'=>1)); ?>

Let me know what results you get with that (url in, url out).  

Also, you need CMSB 2.51 or better for that to work.  If you're using an older CMSB you can either upgrade or manually update the thisPageUrl() function in /lib/common.php (backup first).

Here's the latest version of that function:

// if you set $newQueryValues keys to NULL they will removed
function thisPageUrl($newQueryValues = array(), $queryStringOnly = false) { // $queryStringOnly added in v2.15
  $proto  = isHTTPS() ? "https://" : "http://";
  $domain = @$_SERVER['HTTP_HOST'] ? $_SERVER['HTTP_HOST'] : @$_SERVER['SERVER_NAME'];
  if (preg_match('|:[0-9]+$|', $domain)) { $port = ''; } // if there is a :port on HTTP_HOST use that, otherwise...
  else                                   { $port   = (@$_SERVER['SERVER_PORT'] && @$_SERVER['SERVER_PORT'] != 80) ? ":{$_SERVER['SERVER_PORT']}" : ''; }
  $path   = str_replace(' ', '%20', $_SERVER['SCRIPT_NAME']) . @$_SERVER['PATH_INFO'];

  //
  $query = @$_SERVER['QUERY_STRING'];
  if ($newQueryValues) { // just use the existing query_string unless we need to modify it
    parse_str($query, $oldRequestKeysToValues);

    // v2.51 - double reverse so newly added keys are at beginning of query and don't break urls that need trailing numbers such as ?new=value&page-name=123
    $requestKeysToValues = array_reverse(array_merge(array_reverse($oldRequestKeysToValues), array_reverse($newQueryValues)));

    $query = http_build_query($requestKeysToValues);
  }
  if ($query != '') { $query = "?$query"; }
  $query = rtrim($query, '='); //v2.51 remove trailing = so urls that start like this stay like this: ?page-name-123 and not ?page-name-123=

  //
  if ($queryStringOnly) { return $query; }
  else                  { return $proto . $domain . $port . $path . $query; } // full url
}

Let me know how it goes.  Thanks!

Dave Edis - Senior Developer
interactivetools.com

By Tom - December 2, 2013

Hello,

Thanks for for reply.

However, I have followed all your instruction.

But result still come agent.html?0=&page=1

Below is my full original code

<?php
/* STEP 1: LOAD RECORDS - Copy this PHP code block to the TOP of your page BEFORE anything else. */
require_once "init.php";

list($homepageRecords, $homepageDetails) = getRecords(array(
'tableName' => 'homepages',
'where' => whereRecordNumberInUrl(1),
'limit' => '1',
));

list($listingRecords, $listingDetails) = getRecords(array(
'tableName' => 'listings',
'where' => "agent LIKE '%\t" . getNumberFromEndOfUrl()."\t%'",
'perPage' => '10',
));


$homepage = @$homepageRecords[0]; // get first record

if (!$homepage) { print "Homepage not found!"; exit; }

?>

<!-- show prev/next page links -->
<div class="pagination">
<div class="item-total">Page <?php echo $listingDetails['page'] ?> of <?php echo $listingDetails['totalPages'] ?></div>
<ul>
<?php if ($listingDetails['prevPage']): ?>
<li><a href="<?php echo$listingDetails['prevPageLink'] ?>">Prev</a></li>
<li> <a href="?<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => '1' ))) ?> ">1</a></li>
<li><span>...</span></li>
<?php else: ?>

<?php endif ?>

<?php
if (@!$_GET['page']): $current_page = "1";
else: $current_page = $_GET['page'];
endif; ?>

<?php
$startNumber = max($current_page - 3, 1);
$endNumber = min($current_page + 3, $listingDetails['totalPages']);
?>

<?php foreach (range($startNumber,$endNumber) as $page): ?>

<?php if ($page == $current_page): ?>
<li class="active first-bg-hover"><a><?php echo $page; ?></a></li>
<?php else: ?>
<li><a href="?<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => $page ))) ?>"><?php echo $page; ?></a></li>
<?php endif ?>

<?php endforeach; ?>

<?php if ($listingDetails['nextPage']): ?>
<?php if ($listingDetails['totalPages'] > $endNumber): ?>
<li><span>...</span></li>
<li><a href="?<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => $listingDetails['totalPages'] ))) ?> "><?php echo $listingDetails['totalPages'];?></a></li>
<?php endif ?>
<li><a href="<?php echo $listingDetails['nextPageLink'] ?>">Next</a></li>
<?php else: ?>
<?php endif ?>
</ul>

Please advice .

Thanks a lot

By Dave - December 2, 2013

Hi Tom, 

I identified the problem, array_merge() re-numbers numeric keys.  So that's why this code is failing:

<?php echo http_build_query(array_merge($_REQUEST, array( 'page' => $listingDetails['totalPages'] ))) ?> 

I've updated our thisPageUrl() function to work-around that if you want to give it a try: 


// if you set $newQueryValues keys to NULL they will removed
function thisPageUrl($newQueryValues = array(), $queryStringOnly = false) { // $queryStringOnly added in v2.15
  $proto  = isHTTPS() ? "https://" : "http://";
  $domain = @$_SERVER['HTTP_HOST'] ? $_SERVER['HTTP_HOST'] : @$_SERVER['SERVER_NAME'];
  if (preg_match('|:[0-9]+$|', $domain)) { $port = ''; } // if there is a :port on HTTP_HOST use that, otherwise...
  else                                   { $port   = (@$_SERVER['SERVER_PORT'] && @$_SERVER['SERVER_PORT'] != 80) ? ":{$_SERVER['SERVER_PORT']}" : ''; }
  $path   = str_replace(' ', '%20', $_SERVER['SCRIPT_NAME']) . @$_SERVER['PATH_INFO'];

  //
  $query = @$_SERVER['QUERY_STRING'];
  if ($newQueryValues) { // just use the existing query_string unless we need to modify it
    parse_str($query, $oldRequestKeysToValues);

    // 2.54 - merge manually adding new keys to beginning of query and don't break urls that need trailing numbers such as ?new=value&page-name=123
    //        ... don't use array_merge() as it re-numbers numeric keys which will break urls
    $requestKeysToValues = $newQueryValues;
    foreach ($oldRequestKeysToValues as $key => $value) {
      if (!array_key_exists($key, $requestKeysToValues)) { $requestKeysToValues[$key] = $oldRequestKeysToValues[$key]; }
    }

    $query = http_build_query($requestKeysToValues);
  }
  if ($query != '') { $query = "?$query"; }
  $query = rtrim($query, '='); //v2.51 remove trailing = so urls that start like this stay like this: ?page-name-123 and not ?page-name-123=

  //
  if ($queryStringOnly) { return $query; }
  else                  { return $proto . $domain . $port . $path . $query; } // full url
}

Alternatively, once you start getting more complex pages another approach is to start using named variables such as num=123 to identify which record you want a load.  One last approach, if you have a filename field set under: Admin > Section Editors > Your Section > Viewer Urls (tab) > Filename fields, then you'll get that field value added to the url before the number like this: ?fieldname-field-value-123, and since that will make the field non-numeric it will avoid that bug.

Anyways, thanks for raising this issue, let me know if one of the above solutions work, or feel free to email me direct at dave@interactivetools.com if you'd like me to take a look at the code directly.  I'd be happy to help.  Cheers.

Dave Edis - Senior Developer
interactivetools.com

By Tom - December 3, 2013 - edited: December 3, 2013

Hello Dave,

Thanks for your reply and it's almost perfect.

I have followed your instruction to replace your code in common.php.

And below is the code I followed your instruction to amend.

<!-- show prev/next page links -->
<div class="pagination">
<div class="item-total">Page <?php echo $listingDetails['page'] ?> of <?php echo $listingDetails['totalPages'] ?></div>
<ul>
<?php if ($listingDetails['prevPage']): ?>
<li><a href="<?php echo $listingDetails['prevPageLink'] ?>">Prev</a></li>
<li><a href="<?php echo thisPageUrl(array('page'=>1)); ?>">1</a></li>
<li><span>...</span></li>
<?php else: ?>

<?php endif ?>

<?php
if (@!$_GET['page']): $current_page = "1";
else: $current_page = $_GET['page'];
endif; ?>

<?php
$startNumber = max($current_page - 3, 1);
$endNumber = min($current_page + 3, $listingDetails['totalPages']);
?>

<?php foreach (range($startNumber,$endNumber) as $page): ?>

<?php if ($page == $current_page): ?>
<li class="active first-bg-hover"><a><?php echo $page; ?></a></li>
<?php else: ?>
<li><a href="<?php echo thisPageUrl(array( 'page' => $page )) ?>"><?php echo $page; ?></a></li>
<?php endif ?>

<?php endforeach; ?>

<?php if ($listingDetails['nextPage']): ?>
<?php if ($listingDetails['totalPages'] > $endNumber): ?>
<li><span>...</span></li>
<li><a href="<?php echo thisPageUrl(array( 'page' => $listingDetails['totalPages'] )) ?> "><?php echo $listingDetails['totalPages'];?></a></li>
<?php endif ?>
<li><a href="<?php echo $listingDetails['nextPageLink'] ?>">Next</a></li>
<?php else: ?>
<?php endif ?>
</ul>

<!-- /show prev/next page links --></div>

It's really work and the original url before your amendment was 

agent.html?3&page=1

AND after your amendment, the url like this

agent.html?page=1&3

However, it' works perfectly.

But the final concern is about the Prev and Next URL

The url for the 'Next' is 

agent.html?3&page=1

How to change it to

agent.html?page=1&3

or just leave it alone since it's still work anyway?

Thanks again for your great job!!!!

By Dave - December 3, 2013

Hi Tom, 

Glad it's working better.

But the final concern is about the Prev and Next URL

The url for the 'Next' is 

agent.html?3&page=1

How to change it to

agent.html?page=1&3

or just leave it alone since it's still work anyway?

Hmm, if it works, I'd just leave it alone, but if it doesn't, I think we may have hit a wall with this one.

The numbers on the end of the the URL are meant to be a quick and simple way for developers to set up simple pages, but when you have multiple bits of information in the URL it gets tricky to make sure the number stays in the right place (at the end of the url).  If you continue to have more problems I'd replace the 3 with ?num=3 or &num=3.  This clearly tells the CMS to only return records with a num of 3.  You can then remove the 'where' option from the getRecords() call.  

CMSB automatically filters results based on search terms or queries in the url like this: http://www.interactivetools.com/docs/cmsbuilder/viewer_search.html . Just make sure that if you don't want it doing it on certain viewers to add an option called: 'allowSearch' => false, 

Hope that helps, give it a try, and if you want a hand just email me direct at dave@interactivetools.com and let me know the URL to the page in question.  Thanks!

Dave Edis - Senior Developer
interactivetools.com

By Tom - December 3, 2013

This is great and Thanks a lot Dave!!