Reusing Perch content with item ordering taken from the site navigation structure

A snappy title for this post, and no mistake…

Pulling in content from regions on other pages is a pretty straightforward task in Perch. Let’s say the site structure includes a parent landing page which has a number of child pages. If the parent page needs to show teaser blocks that link to and pull content from the child pages, then this is straightforward and well documented with perch_content_custom.

On a recent project there was an expectation from the site editor that the order of the child pages in the site structure should be respected in the output from perch_content_custom on the parent landing page. And I think that’s quite a reasonable, logical expectation.

Whereas sorting on any existing field is trivial, a little more work is needed to get the output to respect the order of the items in the site structure.

<?php
    $result = perch_content_custom('My Region', [
        'page' => '/*',
        'skip-template' => true,
        'each' => function($item) {
            $item['page_order'] = perch_page_attribute('pageOrder', array(
                '_id' => $item['_pageID'],
            ), true);
            return $item;
        },
    ]);
    
    usort($result, function ($item1, $item2) {
        return $item1['page_order'] <=> $item2['page_order'];
    });

    perch_template('content/_teaser-template.html', $result);
?>

The 3 key steps are:

  1. Return an array from perch_content_custom that uses an each callback to process Perch’s pageOrder (for each child page )and create a custom field called page_order.
  2. Use php’s usort to sort the array on page_order.
  3. Use perch_template to output the content using an appropriate template and passing it the sorted array.

And that does the job nicely.