antknight Posted May 2, 2013 Share Posted May 2, 2013 Hello, I am just using the basic search template and was wondering how to enable pagination for the search results, it is simple enough to do for other pages just can't get it working for search. <?php /** * Search template * */ $out = ''; if($q = $sanitizer->selectorValue($input->get->q)) { // Send our sanitized query 'q' variable to the whitelist where it will be // picked up and echoed in the search box by the head.inc file. $input->whitelist('q', $q); // Search the title, body and sidebar fields for our query text. // Limit the results to 50 pages. // Exclude results that use the 'admin' template. $matches = $pages->find("title|body|sidebar~=$q, limit=50"); $count = count($matches); if($count) { $out .= "<h2>Found $count pages matching your query:</h2>" . "<ul class='nav'>"; foreach($matches as $m) { $out .= "<li><p><a href='{$m->url}'>{$m->title}</a><br />{$m->summary}</p></li>"; } $out .= "</ul>"; } else { $out .= "<h2>Sorry, no results were found.</h2>"; } } else { $out .= "<h2>Please enter a search term in the search box (upper right corner)</h2>"; } // Note that we stored our output in $out before printing it because we wanted to execute // the search before including the header template. This is because the header template // displays the current search query in the search box (via the $input->whitelist) and // we wanted to make sure we had that setup before including the header template. include("./head.inc"); echo $out; include("./foot.inc"); Link to comment Share on other sites More sharing options...
arjen Posted May 3, 2013 Share Posted May 3, 2013 Have you enabled page numbers? It seems you need to render the pagination. Link to comment Share on other sites More sharing options...
antknight Posted May 3, 2013 Author Share Posted May 3, 2013 Thanks argen, Yes I have enabled page numbers but I can't figure out how to incorporate the code to render the pagination? Link to comment Share on other sites More sharing options...
Soma Posted May 3, 2013 Share Posted May 3, 2013 http://processwire.com/api/modules/markup-pager-nav/ 1 Link to comment Share on other sites More sharing options...
arjen Posted May 3, 2013 Share Posted May 3, 2013 It isn't too hard. Make sure you add a limit selector and output the $completeListOfItems->renderPager() function somewhere in your template. 1 Link to comment Share on other sites More sharing options...
antknight Posted May 4, 2013 Author Share Posted May 4, 2013 Thanks for the tips, you will be pleased to know I managed to figure it out! : <?php /** * Search template * */ $out = ''; if($q = $sanitizer->selectorValue($input->get->q)) { // Send our sanitized query 'q' variable to the whitelist where it will be // picked up and echoed in the search box by the head.inc file. $input->whitelist('q', $q); // Search the title, body and sidebar fields for our query text. // Limit the results to 50 pages. // Exclude results that use the 'admin' template. $matches = $pages->find("title|body|sidebar~=$q, limit=50"); $pagination = $matches->renderPager(array( 'numPageLinks' => "5", 'nextItemLabel' => "Next", 'previousItemLabel' => "Prev", 'listMarkup' => "<ul class='MarkupPagerNav'>{out}</ul>", 'itemMarkup' => "<li class='{class}'>{out}</li>", 'linkMarkup' => "<a href='{url}'><span>{out}</span></a>")); $count = count($matches); if($count) { $out .= "<h2>Found $count pages matching your query:</h2>" . "<ul class='nav'>"; foreach($matches as $m) { $out .= "<li><p><a href='{$m->url}'>{$m->title}</a><br />{$m->summary}</p></li>"; } $out .= "</ul>"; } else { $out .= "<h2>Sorry, no results were found.</h2>"; } } else { $out .= "<h2>Please enter a search term in the search box (upper right corner)</h2>"; } // Note that we stored our output in $out before printing it because we wanted to execute // the search before including the header template. This is because the header template // displays the current search query in the search box (via the $input->whitelist) and // we wanted to make sure we had that setup before including the header template. include("./head.inc"); echo $out; echo $pagination; include("./foot.inc"); 1 Link to comment Share on other sites More sharing options...
arjen Posted May 4, 2013 Share Posted May 4, 2013 Thanks for the feedback. Glad you sorted it out! Link to comment Share on other sites More sharing options...
Roope Posted June 18, 2013 Share Posted June 18, 2013 Hello guys, need a little help here. I'm also trying to set pager for search results but the whole query string seems to be stripped out in links that pager renders. // page url http://domain.com/search/?vendor[]=1087&vendor[]=1212&light_source_amount=&product_family=&safety_class=&voltage=&height_min=&height_max=&length_min=&length_max=&width_min=&width_max=&depth_min=&depth_max=&hanging_height_min=&hanging_height_max=&diameter_min=&diameter_max= // pager urls http://domain.com/search/?page=2 http://domain.com/search/?page=3 http://domain.com/search/?page=4 Can it be because the query string is so freaking long? Link to comment Share on other sites More sharing options...
Wanze Posted June 18, 2013 Share Posted June 18, 2013 Roope, You need to put your sanitized GET vars into the whitelist: $input->whitelist('q', $q); Link to comment Share on other sites More sharing options...
Roope Posted June 18, 2013 Share Posted June 18, 2013 Aah, ok.. now it's looking better. Thanks! Still not there yet.. Now pager url looks like this: http://domain.com/search/?vendor=1087|1212&light_source_amount=&product_family=&safety_class=&voltage=&height_min=&height_max=&length_min=&length_max=&width_min=&width_max=&depth_min=&depth_max=&hanging_height_min=&hanging_height_max=&diameter_min=&diameter_max=&page=2 Notice pipes as vendor delimiters. OK, then I click to page 2 but nothing happens. Same results and pager page 1 is active. Only difference is that now pager urls have changed to use plus sign as delimiter: http://domain.com/search/?vendor=1087+1212&light_source_amount=&product_family=&safety_class=&voltage=&height_min=&height_max=&length_min=&length_max=&width_min=&width_max=&depth_min=&depth_max=&hanging_height_min=&hanging_height_max=&diameter_min=&diameter_max=&page=2 Selector for results remains same all the time: id>1, limit=20, template=product, vendor=1087|1212 Link to comment Share on other sites More sharing options...
ryan Posted June 20, 2013 Share Posted June 20, 2013 The biggest issue that I can see here is that you don't have page numbers enabled for your template. ProcessWire putting in the "page=2" is a signal of that. So before you do anything else, go and enable page numbers by editing your 'search' template–you'll see the option to enable page numbers on the URLs tab. When it comes to dealing with your 'vendor' field, I recommend whitelisting it to a string in whatever format you want to extract it. For instance, maybe you want to use commas as a separator rather than pipes. You can whitelist it like this: $input->whitelist('vendor', implode(',', $vendors)); // if vendors is an array $input->whitelist('vendor', str_replace('|', ',', $vendors)); // if vendors is a PageArray Though you could certainly stick with "|" pipes if you preferred. But what I don't want to see you do is bundle that right from $input->get->vendor into a selector without validating it first. So switching to another separator makes that intention a little more clear. For instance, your form processor might capture and sanitize the vendor variable like this: if($input->get->vendor) { if(is_array($input->get->vendor)) { // array from form submission $dirty = $input->get->vendor; } else { // convert from your CSV string to array $dirty = explode(',', $input->get->vendor); } $vendor = array(); foreach($dirty as $id) $vendor[] = (int) $id; // sanitize to INTs $vendor = implode('|', $vendor); // convert to 123|456|789 string, ready for selector } else { $vendor = ''; } 1 Link to comment Share on other sites More sharing options...
Roope Posted June 20, 2013 Share Posted June 20, 2013 Thank you very plenty Ryan! You're absolutely right - I made such a rookie mistake and didn't have page numbers enabled from template setup. Once I did it paging started working like excepted. Sorry about that. Right now I have function that makes selector string for PW from post or get data and I have this excactly problem with PW page field values that it can be either array or string, with values separated by plus sing or empty space. If I just whitelist data like you suggest, I wouldn't have to do all checking and exploding at all. If I got this right.. Will test it later since it's my birthday and midsummer festival here in Finland so God Bless PW and hyvää juhannusta to everybody! Link to comment Share on other sites More sharing options...
ryan Posted June 22, 2013 Share Posted June 22, 2013 Happy Birthday Roope! I personally don't like having arrays in GET variables (they are overly verbose and make ugly URLs). But if you want the MarkupPagerNav to keep arrays in their native GET variable state, you can tell it to by using the 'arrayToCSV' option and setting it to false. echo $mypages->renderPager(array('arrayToCSV' => false)); 1 Link to comment Share on other sites More sharing options...
Roope Posted June 27, 2013 Share Posted June 27, 2013 Thanks Ryan! Man I was struggling with this but once I got the logic everything went smoothly. I totally agree with what you said about arrays in GET vars. Now after form submission they are really ugly since it's submitted as is. Things get better when you move to different pages. Maybe I should send form by jQuery so I could make prettier urls by default or how would you do it? I did GET var whitelisting like this - pretty much as you suggested: <?php // open new instance of our import module since // it holds field names and types we can use for validation $deco = new DecoImport(); // there's some get data if ($input->get->count() > 0) { foreach ($input->get as $key => $value) { // skip undefined fields if (array_key_exists($key, $deco->fieldTypes)) { // skip empty values if (empty($value)) continue; // sanitize key $key = $sanitizer->selectorField($key); // sanitize value if ($deco->fieldTypes[$key] == 'page') { if (is_array($value)) $dirty = $value; else $dirty = explode("|", $value); $value = array(); foreach($dirty as $id) $value[] = (int) $id; // sanitize to INTs $value = implode("|", $value); } else $value = $sanitizer->selectorValue($value); // whitelist data $input->whitelist($key, $value); } } } Link to comment Share on other sites More sharing options...
ryan Posted June 29, 2013 Share Posted June 29, 2013 Maybe I should send form by jQuery so I could make prettier urls by default or how would you do it? The need to have arrays in GET vars honestly doesn't come up very often in my projects. Usually when I'm using arrays, it's with POSTs. But if you want to avoid the array appearance in your URLs, you could always solve it by intercepting the request and reconstructing it to have your desired style, i.e. if(!empty($input->get->array_var)) { $csv = ''; foreach($input->get->array_var as $value) $csv .= ((int) $value) . ","; $session->redirect("./?csv_var=$csv"); } Is it worth the overhead? Probably not, and all GET variables are ugly to some extent. But just showing it's possible to do without going the javascript route. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now