Callbacks in Perch Custom functions with each

A short post detailing how to add a callback function to a loop in Perch.

Working on a site for a course I created a listing of all of my lessons as a Perch Runway Collection. This gave me the ability to template the lesson with Blocks, adding code sections, video and text. I then used the Categories functionality to create top level categories for my courses with sub-categories to represent modules – groups of lessons.

Categories

With my categories created I could add a lesson to a module by selecting the category in the Perch Admin.

Select Category

To display this information on the landing page for a course I then needed to loop through my categories, and display the name of that module with the lessons listed underneath.

Looping through and displaying the categories was easy using the perch_categories function, passing in the name of the category Set. I’m also filtering on the top level category, in this case “css-basics” to get the sub-categories. These sub-categories are my modules.

$currentPath = 'css-basics';
$course = perch_categories(array(
  'set'=>'courses',
  'template'=>'course-module.html',
  'filter'=>array(
    array(
      'filter'=>'catPath',
      'match'=>'contains',
      'value'=>$currentPath
    ),
    array(
      'filter'=>'catParentID',
      'match'=>'gt',
      'value'=>'0'
    ),
  ),
));

This gets me a list of all of the sub-categories of the category ‘css-basics’ output by a template course-module.html.

The template course-module.html is a standard category template saved in perch/templates/categories. I’ve added an additional field – a hidden field with an ID of lessons. I want to populate this field with the lessons that have been added to the current module as we go through the loop.

<perch:before>
  <div class="wrapper">
    <div class="page-listing">
      <ul>
</perch:before>
<li>
  <h2><perch:category id="catTitle" type="smarttext" label="Title" required="true" /></h2>
  <perch:category id="catSlug" type="slug" for="catTitle" suppress="true" />
  <perch:category id="desc" type="textarea" label="Description" editor="markitup" markdown="true" size="s" />

    <perch:category id="lessons" type="hidden" encode="false" />
</li>
<perch:after>
    </ul>
  </div>
</div>
</perch:after>

To get my lessons from the Collection I add a key each to the array of options for the perch_categories function.

$currentPath = 'css-basics';
$course = perch_categories(array(
  'set'=>'courses',
  'template'=>'course-module.html',
  'filter'=>array(
    array(
      'filter'=>'catPath',
      'match'=>'contains',
      'value'=>$currentPath
    ),
    array(
      'filter'=>'catParentID',
      'match'=>'gt',
      'value'=>'0'
    ),
  ),
  'each' => function($item) {
      $item['lessons'] = perch_collection('lessons',array(
        'category'=>$item['catPath'],
        'template'=>'lessons/lesson-excerpt.html'
      ),true);

      return $item;

    },
));

The value of each is a function, this function runs each time we go through the loop and returns the lessons for that category templates with my lesson-excerpt.html template. This then populates $item['lessons'] which in turn populates the lessons template tag in my category template.

This functionality is documented on the perch_content_custom page, but works wherever there is a custom function – so in many official Apps, Categories and Collections.