Jump to content
a-ok

Allow Page Numbers isn't 404'ing when content doesn't exist...

Recommended Posts

Hi folks,

I've set up some infinitescroll on manual trigger on a Journal section of my site, all fine and set up, but there's a slight issue that the 'Allow Page Numbers' isn't returning a 404 even when there isn't more 'pages'. So, the infinitescroll never fails... or stops.

For example, I have a /journal/page1 which is fine, and has posts, and a /journal/page2 but then, technically, /journal/page3 shouldn't exist as all the last post is on page2, but even if I put /journal/page99 it still returns a page, rather than a 404.

Looking at the tutorials, this is even the same for the tutorial: https://processwire.com/docs/tutorials/how-to-use-url-segments/page99

I know I need to build a throw new Wire404Exception(); into my template, but I am unsure how to manage this?

Any thoughts?

Thanks!

R

Share this post


Link to post
Share on other sites

your isotope implementation should have the max pages set in a data attribute, e.g.

<a href="#" data-pages="4" data-page="1" data-link="http://mysite.com/page2/">More Items...</a>

this may or not be visible if you are triggering the load at reaching the end of the page;

you would be able to reuse your pagination vars for the data-pages value (ceil items_per_page/total_items for example);

your script needs to be smart enough not to ask for another page after it has loaded the last page, the data-page value gets updated each time you load the next page's results;

Share this post


Link to post
Share on other sites

So, the infinitescroll never fails... or stops.

That's why it's infinite :)

Share this post


Link to post
Share on other sites

Thanks for the replies but I think you're missing the point. The issue is not to do with infinite scroll, but rather Processwire and how it doesn't run a 404 page when there is no more content on Allow Page Numbers...

Share this post


Link to post
Share on other sites

The solution would be Javascript rather then ProcessWire. From the ProcessWire side you have to tell the javascript when to stop. I don't know Isotope, but if I were you I would follow the recommendations of Macrura. 

Share this post


Link to post
Share on other sites

ProcessWire must leave it up to you to handle those 404 errors, as it cannot know when to throw that error. Maybe your result of find() will get pages added at a later stage of the process, which wouldn't get called if pw would throw an 404 error right after the find() call. 

$list = $pages->find("stuff=selected, limit=10");

// if list is empty and it's not the first page
if(!$list->count() && $input->pageNum != 1) throw new Wire404Exception();

Share this post


Link to post
Share on other sites

your infinite scroll will keep triggering unless you put a limit;

plus, even if you stop the load after it detects no more items, you would still have to load that 404 page to find out, so then you wouldn't be able to show the "no more posts to load" message at the right time;

Share this post


Link to post
Share on other sites

@Macrura

But solely relying on the 404 error does account for pages, that may have been added after the initial page load, while setting the max pages limit previously isn't that flexible.

Share this post


Link to post
Share on other sites

@Macrura

But solely relying on the 404 error does account for pages, that may have been added after the initial page load, while setting the max pages limit previously isn't that flexible.

that's a good point, though the sites i'm using infinite scroll on are not updated that often and are cached - i would think it a somewhat rare occurrence for a viewer to miss out on an item that was added between their page load and when they hit the trigger for the last page...

Share this post


Link to post
Share on other sites

Hi @LostKobrakai, many thanks for this. This is the sort of solution I was after... however this doesn't seem to throw a 404 even when I am on /page7/ where only /page3/ was the last page that had any content.

<?php $journals = $pages->find('parent=/journal/, sort=-journal_date, limit=1'); ?>
<?php if (!$journals->count() && $input->pageNum != 1) throw new Wire404Exception(); ?>

I've actually worked out that it is bringing in my 404 template, but keeping the URL as /journal/page7/, for example, so infinitescroll is thinking this is just another page and not actually a 404...

Share this post


Link to post
Share on other sites

To reiterate my point above... if I go to the following URL...

https://processwire.com/docs/tutorials/how-to-use-url-segments/page99 it works, even though it shouldn't, but if I go to https://processwire.com/docs/tutorials/how-to-use-url-segments/dfdsfs it 404s. If I set up my code, like you suggested, and use throw new Wire404Exception()... it doesn't treat it like the second URL, it just shows my 404 template but keeps the same URL /page99

Share this post


Link to post
Share on other sites

It's up to you what to do when you throw the 404 error. Probably you would need to do a redirect ($session->redirect...) but in case of infinitescroll, you may need to send a message (eg. "No more posts").

Share this post


Link to post
Share on other sites

I've had to do:

<?php $fourohfour = $config->urls->root . 'http404/'; ?>
<?php if (!$journals->count() && $input->pageNum != 1) $session->redirect($fourohfour); ?>

Which in my console shows:

XHR finished loading: GET "http://localhost/Freelance/5th-studio/journal/page3"
GET http://localhost/Freelance/5th-studio/http404/ 404 (Page Not Found)

So, this fixes things for me, but the issue still lies... why would it retrieve /page8/ when nothing exists on it? Surely the 'Allow Page Numbers' shouldn't work infinitely and eventually when it returns blank auto 404s? And why doesn't 'throw new Wire404Exception()' actually throw a 404 page but rather include it in the template rather than a full refresh like a normal 404 page should do?

Share this post


Link to post
Share on other sites

As I tried to tell you above ProcessWire cannot know how to handle pagination pages, where the selector returns an empty set. Pagination isn't more than just limiting the returned set of pages. PW cannot guess what else you're doing on that page, or if maybe this empty set will be modified later. Blindly throwing 404 errors would make this system greatly more inflexible. You can always handle those things on your own just like you need it.

To iterate on your 404 problem: 404 errors do always respond directly on the requested url, no matter where in pw. Only the status-code will change to 404. 

post-874-0-58072800-1440601905_thumb.png

  • Like 2

Share this post


Link to post
Share on other sites

Thanks, this makes lots of sense now. Really appreciated and can understand why it's important that it is left as flexible as possible.

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By jacmaes
      I have a series of videos, and the following search form (translated into English here) that allows to filter these videos on the frontend:

      I've built a few of these search forms, but only with text fields, selects and radio buttons. Here I'm using an array with checkboxes ("Level" field above), and it's causing me grief when I try to paginate these results. I've done a lot of searching in the forum and spent too many hours to try to get it to work. Here's how I'm building the selector:
      <?php if(count($input->get)): // Level is an array. Code adapted from Ryan's snippet here: // https://processwire.com/talk/topic/3472-enable-pagination-for-search-results/?tab=comments#comment-38042 if($input->get->level) { $level = array(); foreach($input->get->level as $id) $level[] = (int) $id; // sanitize to INTs $level = implode('|', $level); // convert to 123|456|789 string, ready for selector } else { $level = ''; } $data = array( 'training_type' => array('=', (int) $input->get->training_type), 'duration' => array('=', (int) $input->get->duration), 'level' => array('=', $level), 'limit' => array('=', (int) $input->get->limit) ); $selector = ''; // iterate through the $data we made above to create a selector string foreach($data as $field => $a) { list($operator, $value) = $a; if(empty($value)) continue; // send value to the whitelist so that it can be used in pagination $input->whitelist($field, $value); // append to our selector string $selector .= "$field$operator$value, "; } $videos = $page->children("$selector"); When I hit search, I get the expected results. So far so good. The GET parameters are the following with the options selected in the screenshot above:
      videos/?level[]=1476&level[]=1477&training_type=1473&duration=1485&limit=10 $selector echoes the following as the "level" field is an array with a pipe character:
      level=1476|1477, training_type=1473, duration=1485, limit=10 Now, when paginating these results, the following page (page 2) shows these GET parameters:
      videos/page2/?level=1476|1477&training_type=1473&duration=1486&limit=10 And I think that's where the problem lies. The "level" field is "lost" and I'm getting more results than expected on subsequent pages. If I manually add "page2" to the initial results in the URL, just to test, everything works fine:
      videos/page2/?level[]=1476&level[]=1477&training_type=1473&duration=1486&limit=10 But how can I achieve this in code? Do I need to revert to "level[]=1475&level[]=1477" instead of "level=1476|1477" for the pagination to work correctly, and can you PHP gods illuminate me?
      Any help would be really appreciated, really.
    • By Peter Knight
      Hi guys
      is there a checklist of items I should consider for diagnosing a series of pages which display a 404 error?
      Basically I have built a Blog and all my posts are under a folder called 'Posts'. Some of these pages successfully display while others display a 404 page. 
      This is what I have confirmed so far...
      1. All pages are within the same root folder 'Posts'
      2. All pages have the same template and fields completed
      3. All pages have the same properties under Settings > Who can access this page
      4. Pages have no redirects in place
      5. Pages have no special characters or anything funky in the URL slug
      There are no errors showing in the log either so I am stuck 😕
      Thanks
    • By christophengelmayer
      Hi everyone,
      I'm working on a CLI script that renders paginated pages.
      Therefore I iterate trough paginated pages and set the page number and render the result.
      My problem is, after calling the render function for the first time, the output doesn't change even if I change the page number.
       
      DEMO:
      I'm using a template that renders a pagination of its children:
      <?php echo $page->children("limit=3")->render(); ?> I can view the paginated results in the Browser:
      /page-rendering-pagination/ /page-rendering-pagination/page2 /page-rendering-pagination/page3 ... When trying to render the different pages using the API I always get the first result, even if I change the page Number.
      <?php namespace ProcessWire; include('./index.php'); wire('input')->setPageNum(1); $p = wire('pages')->get('/page-rendering-pagination'); var_dump($p->render()); // renders first three items wire('input')->setPageNum(2); var_dump($p->render()); // also renders the first three items Am I missing something? Is there some kind of caching mechanism that I'm not aware of?
      Thanks for your help.
    • By dragan
      Quick question: Is it possible to use PW's pagination for other things than PageArrays? i.e. query custom database tables and paginate the results? Has anyone ever tried it?
    • By brdje
      Greetings,
       
      I've created a product database which all use the template product.php and are published on the website.
      I'm trying to create an overview table with pagination of all the products, but using $pages->get does not return an object, only the object title.
      $products = $pages->get("template=product, limit=10"); This returns 10 strings in the frontend but not the object. When looping over the result set to get product fields, i get the following error:
      Notice: Trying to get property 'title' of non-object
       
      Because the product database is fairly large, i've added a pagination using the same query and this does return all the pages, but i can't click on the links that the paginator renders.
      $results = $pages->find("template=product, limit=10"); if($results->getTotal() > 10) { echo $results->renderPager(array( "nextItemLabel" => "Volgende", "previousItemLabel" => "Vorige", "currentItemClass" => 'active' )); }
      I've added the option in the template to allow page numbers. When i navigate to the link manually, i still end up seeing the 10 first products.
       
      I've tried changing several settings around, but i'm a bit stuck on how to resolve these issues. Do you have any advice what I need to adjust?
      Thanks in advance for your feedback.
       
       
×
×
  • Create New...