True Smarty Pagination

While my earlier example illustrated the concept of automating pagination with Smarty in your Movable Type archives, I had a couple of problems with it.

First and foremost was that if someone “hacked” the URL, to submit their own value for a start range, then the links wouldn’t work right. They might start on entry number 2 instead of entry 1, and while the previous link would say 1-1 (itself a bit ugly), it would actually render entries starting with 1, but the page would biuld through the default limit or the end of the category, whichever came first.

So I played with adding a user-specified limit (with a maximum size). But it had the same problem, in that if someone specified a limit that wasn’t that of the default, it could create strange results with the links and what you would get when you clicked them. Back to the drawing board.

I figured the only way to approach this was to go with true pagination – that is, allow the user to select a page, not an entry. That page would always contain the same entries (the last page, of course, may vary, and new pages may be added). But they would not be able to start from somewhere in the middle of the page – that just wouldn’t work.

Step one is to find the total number of entries. As with my earlier example, I’m using the category count to find the total. You could use other formulas, depending on where you are using the pagination. The point is just to get a count in the right variable.

  {{* total number of entries *}}
  {{capture assign="count"}}<$MTCategoryCount>{{/capture}}

Step two is to set a number of entries per page. I set the limit variable to the number of entries I’d like per page.

  {{* entries per page *}}
  {{assign var="limit" value="12"}}

Step three is to take that number and figure out how many pages you will have by using that number. By using the PHP function @ceil, I don’t have to worry about fractions.

  {{* number of pages *}}
  {{assign var="pages" value=$count/$limit|@ceil}}

Finally, you’ll need to take those values and set your MTEntries container appropriately. I used something like this:

  {{assign var="lastn" value=$limit}}
  {{math assign="offset" equation="($p-1)*$limit"}}
  <MTEntries lastn="`$lastn`" offset="`$offset`">

This section takes the variable called limit that we set earlier and populates the lastn attribute of the MTEntries container. Similarly, the value of offset is used to set, appropriately enough, the offset attribute in the same container. The calculation for setting the offset variable simply takes the page number, subtracts 1 and multiplies by the value of limit. In other words, it accounts for the entries on the current page.

In the end, the calculations were a bit more complex, but I like the results a lot better. Check out the archives (you’ll need to browse individual categories to see the change) and let me know what you think.

As always, if you’re interested in something like this but are having trouble doing it yourself, let me know and we can talk rates. This is what I do, and I am available for consulting work regardless of whether you are an individual, a small company or a multinational conglomerate.

Update: Thanks once again to Brad for even more help. Couldn’t do it without him.


Posted

in

Comments

13 responses to “True Smarty Pagination”

  1. Sarah Avatar
    Sarah

    So, to summarise what’s in this entry and comments (and your previous entries), the best method would be to replace the existing opening tag with the following:

    {{* total number of entries *}}
    {{capture assign="count"}}<$MTCategoryCount>{{/capture}}
    {{* entries per page *}}
    {{assign var="limit" value="5"}}
    {{* number of pages *}}
    {{assign var="pages" value=$count/$limit|@ceil}}
    {{if $smarty.request.p > 1}}
    {{math assign="p" equation="min($pages,x)" x=$smarty.request.p}}
    {{else}}
    {{assign var="p" value="1"}}
    {{/if}}
    {{assign var="lastn" value=$limit}}
    {{math assign="offset" equation="($p-1)*$limit"}}
    {{if $p > 1}}
    <a href="?p={{$p-1}}">Previous</a>
    {{/if}}
    {{if $p < $pages}}
    <a href="?p={{$p+1}}">Next</a>
    {{/if}}
    <MTEntries lastn="`$lastn`" offset="`$offset`">

    Is that correct?

  2. Chad Everett Avatar

    Alex, if you’ve truly got a bug, you may want to file it with Six Apart.

    That said, I’m pretty certain that it works okay, as I’m using it here without issue, so far as I am aware.

  3. Alex Sancho Avatar

    Thanks for sharing this, it’s really the best method for a dynamic pagination.

    With version 3.2 I’m using it in some different ways, but since I’ve updated to 3.31, monthly and category archives always shows “lastn” entries, ignoring offset parameters.

    Any idea?