Leo's MovableType Tips

by Leo A. Notenboom

by Ask Leo!

Next and Previous - Within a Category

MT automatically gives you the next and previous items for your individual archives with <MTEntryNext> and <MTEntryPrevious> items. The problem is that's within the global list of all entries within your blog. What if you wanted to link to the next or previous item within a given category?

As an example, check out any of the entries on Forwarded Funnies. There, in the upper right, you'll see not only a previous and next for "All Entries", but a separate previous and next for entries of the same rating as the current. In other words a previous and next for all the "G-Rated" entries if the current item is itself G-rated.

Needless to say, ratings within Forwarded Funnies are simply separate MT categories.

My approach uses a combination of PHP code generated from a category archive template, and a server-side include, or "SSI", in the individual entry archive template.

The category archive template I added is this:

<?
    $szID = $_GET['id'];
    $szOp = $_GET['op'];
    $szText = $_GET['text'];

    <MTEntries sort_order="ascend">
     $rgArchive[<$MTEntryID$>] = "<$MTEntryPermalink$>";
     $rgTitle[<$MTEntryID$>] = <<<H<$MTEntryID$>
<$MTEntryTitle$>
H<$MTEntryID$>;
    </MTEntries>

    if (array_key_exists ($szID, $rgArchive))
      {
      while (key ($rgArchive) != $szID)
        {
        $szPrev = key ($rgArchive);
        next ($rgArchive);
        }
      $szNext = next ($rgArchive);
      $szNext = key ($rgArchive);
      
      if (("next" == $szOp) && ("" != $szNext))
        echo "$szText <a href=\"" . $rgArchive[$szNext] 
            . "\">" . $rgTitle[$szNext] . "</a>";
      elseif (("prev" == $szOp) && ("" != $szPrev))
        echo "$szText <a href=\"" . $rgArchive[$szPrev]
            . "\">" . $rgTitle[$szPrev] . "</a>";
      }
?>

The MT Entries section generates PHP code such as this:

  $rgArchive[500] = "http://www.forwardedfunnies.com/do_not_be_late_000500.html";
  $rgTitle[500] = <<<H500
Do Not Be Late
H500;
  $rgArchive[501] = "http://www.forwardedfunnies.com/jesus_mary_joseph_and__000501.html";
  $rgTitle[501] = <<<H501
Jesus, Mary, Joseph and ...
H501;

In other words, it defines two arrays that map the item's ID to its Title and Permalink. When used, this PHP code takes an entry ID as a parameter, and then outputs a link to either the next or previous item in the list.

We'll see exactly how that's used in just a second. First, I have to make sure that the files generated when this template is built are named appropriately.

In the weblog's Settings, in the Publishing tab, down in Archive Mapping, I created a new Archive Mapping for our new template. It is, as we said, a Category archive, using the new template we added above.

Most importantly, I defined the Archive File Path to be: "catnav_%c.php"

Archive Mapping for Category Navigator

This will then cause a category navigator, as I call it, to be built for each category defined in the system. For example:

catnav_grated.php
catnav_pgrated.php
...

Now, to hook it up with the individual entries.

In the individual entry template, I place this code:

<MTEntryCategories>
  <br />
  <a href="<$MTCategoryArchiveLink$>"><b><$MTCategoryLabel$></b></a><b> Entries:</b><br />
  <!--#include VIRTUAL="catnav_<$MTCategoryLabel dirify="1" $>.php?id=<$MTEntryID$>&op=next&text=Next:" --><br />
  <!--#include VIRTUAL="catnav_<$MTCategoryLabel dirify="1" $>.php?id=<$MTEntryID$>&op=prev&text=Previous:" --><br />
</MTEntryCategories>

There are several interesting parts to this fragment, so I'll go over them one by one.

First, note the use of "<MTEntryCategories>". While within Forwarded Funnies, each item is assigned only one category, that's not a required limitation. So the code that we'll generate here will be repeated once for each category that this entry is assigned.

I start with a link to "<$MTCategoryArchiveLink$>" - that's a link to the standard category archive page that simply lists all entries that have been assigned the category. Nothing really new here.

I invoke the appropiate "catnav_??.php" within an SSI. This requires a little more detailed explanation:

Note that I include the SSI twice - once with parameters indicating that the next item be fetched, and once again for the previous.

When all is said and done, each entry has a next and previous link within their category, something like this:

G-Rated Entries:
Next: Horse For Sale
Previous: Colorado Barbie

Or, in HTML:

<a href="http://www.forwardedfunnies.com/grated.html"><b>G-Rated</b></a><b> Entries:</b><br />
Next: <a href="http://www.forwardedfunnies.com/horse_for_sale_009802.html">Horse For Sale</a><br />
Previous: <a href="http://www.forwardedfunnies.com/colorado_barbie_009819.html">Colorado Barbie</a><br />