Jump to content

Search with merged PageArrays + pagination = not working


isellsoap
 Share

Recommended Posts

Hey there.
 
The pagination for my search isn’t working. I guess it has something to do with the merging of PageArrays beforehand. Take a look at the (simplified) search.php:

$out = "";

if ( $q = $sanitizer->selectorValue( $input->get->q ) ) {

	$input->whitelist( "q", $q );

	$pa = new PageArray();
	$value = $pages->find( "title%=$q" );
	
	$pa->import( $pages->find( "template=abc, …|…|…=$value" ) );
	$pa->import( $pages->find( "template=abc, title%=$q" ) );

	$result = $pa->find( "start=0, limit=4" );
	$pagination = $result->renderPager();

	$count = count( $pa );

	if( $count ) {

		$out .= "<h2>Search results found</h2>";
		$out .= "<ul>";

		foreach( $result as $r ) {
			$out .= "<li>{$r->title}</li>";
		}

		$out .= "</ul>";
		$out .= $pagination;

	} else {
		$out .= "<h2>Sorry, no results were found</h2>";
	}
} else {
	$out .= "<h2>Please enter a search term in the search box</h2>";
}

include("./head.inc");

echo $out;

include("./foot.inc");

Pagination names are activated for the search template and the output of the pagination list is correct. When I go to "page2", "page3", etc. the result is always the very first 4 matches. Any help is appreciated, thanks!

p.s.: I have to do the merging because one time I search for page references to a page (the "…" in the code) and one time for the title of a page with the template "abc". (offtopic: if you know a better solution to this just let me know) :)

Link to comment
Share on other sites

I ran into this too. See the code and explanation if the other post. Basicly you have to merge all $pages->find and include them again in a find. This feels very hacky (and potentially has issues with performance), so it would be preferred to use one $pages->find. 

$latestPosts = $pages->find("template=post, frontpage=1, max_date>=$today")->add($pages->find("template=post, frontpage=1, max_date=null"));

$pages->find("id=$latestPostsMaxDate, limit=3, sort=-created");
Link to comment
Share on other sites

Pagination module doesn't work with in memory page arrays. Once you manipulate or merge arrays you operating in memory. Pager does need a single find db query to work. You'd need to create your own pager functions for in memory page arrays using the start and limit selectors.

  • Like 4
Link to comment
Share on other sites

Ha, I did it!

Instead of 

$pa = new PageArray();
$value = $pages->find( "title%=$q" );
	
$pa->import( $pages->find( "template=abc, …|…|…=$value" ) );
$pa->import( $pages->find( "template=abc, title%=$q" ) );

I wrote this

$pa = $pages->find( "template=abc, bla1.title|bla2.title|bla3.title|…|title%=$q, limit=4" );

I don’t search for the page references but for the titles of the page references with ".title". Works like a charm.  :-)

  • Like 3
Link to comment
Share on other sites

On a different note: I’d like to throw a 404 error when a page is reached where no content appears. E.g. pagination only goes until "page5" but when I type "page6" in the address bar it doesn’t throw an error. Can one of you reproduce this behaviour?

I tested it a bit further and apparently the pagination limit is 999. :-)

Link to comment
Share on other sites

$value = $pages->find( "title%=$q" );
$pa->import( $pages->find( "template=abc, …|…|…=$value" ) );
$pa->import( $pages->find( "template=abc, title%=$q" ) );

What should that do? You have to explaing a little more for a short minded like me. :)

I have an example that shows how to construct your own pager using the PW PagerNav class:

// include paginator class
require_once($config->paths->MarkupPagerNav . "PagerNav.php");

$pa = new PageArray();
$res1 = $pages->find("template=xyz, title%=space");
$res2 = $pages->find("template=abc, title%=hal");
$pa->import($res1);
$pa->import($res2);

// config paginator
$baseUrl = $page->url;
$limit = 4;
$start = ($input->pageNum - 1) * $limit;
$total = $pa->getTotal();
$pagerNav = new PagerNav($total, $limit, $input->pageNum);
$pager = $pagerNav->getPager();

// construct paginator markup
foreach($pager as $link) {
    if($link->pageNum == $input->pageNum) $class .= "on";
    if($link->type == "separator") $item = '…';
        else $item = "<a class='$class' href='{$baseUrl}page{$link->pageNum}/'>$link->label</a>";
    $pagerMarkup .= "<li>$item</li>";
}
// output paginator markup
echo "<ul class='pager'>" . $pagerMarkup . "</ul>";

echo "total: $total<br/>";
echo "start: $start<br/>";
echo "limit: $limit<br/>";

echo "<ul>";
foreach($pa->find("start=$start, limit=$limit") as $p){
    echo "<li>$p->title</li>";
}
echo "</ul>";
 

Also in my ever growing gist examples https://gist.github.com/somatonic/5420536

  • Like 5
Link to comment
Share on other sites

On a different note: I’d like to throw a 404 error when a page is reached where no content appears. E.g. pagination only goes until "page5" but when I type "page6" in the address bar it doesn’t throw an error. Can one of you reproduce this behaviour?

I tested it a bit further and apparently the pagination limit is 999. :-)

Yeah that normal and expected behaviour. And who would enter page number manually anyway?

Edit: ah, to manually call a 404 you do

throw new Wire404Exception();
Link to comment
Share on other sites

Yeah that normal and expected behaviour. And who would enter page number manually anyway?

I guess it‘s just a matter of principle. Why would I want a page that doesn’t make sense at all but doesn’t throw an error? Better to throw an error. Do you know how to get the number of the last page generated in a pagination?

What should that do? You have to explaing a little more for a short minded like me. :)

Like I wrote in the starting post:

p.s.: I have to do the merging because one time I search for page references to a page (the "…" in the code) and one time for the title of a page with the template "abc". (offtopic: if you know a better solution to this just let me know)

But I got a solution by now. :-)

Link to comment
Share on other sites

Uhm? I totally agree, but that wasn’t what I meant. :-)

Like for instance: if the pagination has 5 pages, is there a way to get the last page of that pagination so that when someone tries to go to "page6" I can throw an 404 exception?

Link to comment
Share on other sites

Well you test for if any results are found at all.What I do is check for if theres a result and show "no results found" or "out of range" and a link to first, or a redirect. Not sure its a good idea to show the a 404, like you also dont show one on a search result page if theres nothing found.

Link to comment
Share on other sites

Like for instance: if the pagination has 5 pages, is there a way to get the last page of that pagination so that when someone tries to go to "page6" I can throw an 404 exception?

It's not a bad idea to throw a 404 in that condition. Though the only way someone could access such a page is by manually editing the address bar URL. But if you want to account for it, here's how you could do it:

$results = $pages->find("your selector goes here"); 
if($input->pageNum > 1 && !count($results)) throw new Wire404Exception();
Link to comment
Share on other sites

  • 4 months later...

THen there's this $a->setTotal() $a->setLimit() $a->setStart() on page arrays we can use to configure built in MarkupPagerNav to work with merged page array in memory. Kind same as my above example but much simpler.

/**
* here is a example with using the built in pager
* we can use $a->setTotal($n) to configure page array to work with pager
*/

// create new page array for storing pages
$pa = new PageArray();
$res1 = $pages->find("template=mytemplate");
$res2 = $pages->find("template=house");

// import the found pages
$pa->import($res1);
$pa->import($res2);

// configuration for pagination needed
$limit = 10;
$total = $pa->count();
$start = ($input->pageNum-1)*$limit;

// example output with limited list we filter from the complete page array
foreach($pa->filter("sort=-created, limit=$limit, start=$start") as $p){
     echo "<p>$p->title</p>";
}

// page array let's you set the parameters for pagination manually
$pa->setLimit($limit);
$pa->setTotal($total);
$pa->setStart($start);

// now the renderPager() on the page array works as usual
echo $pa->renderPager();
 
Added this to the previous gist snippet here https://gist.github.com/somatonic/5420536#file-paginator_manual-php
  • Like 6
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...