Callback Functions with each
Any of the _custom
functions in Perch can take a callback which allows for some processing of the item before it is templated. In this example I create a Category listing and then use each
to pass in templated Collection data.
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.
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([
'set' => 'courses',
'template' => 'course-module.html',
'filter' => [
[
'filter' => 'catPath',
'match' => 'contains',
'value' => $currentPath
],
[
'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></h2>
<perch:category id="catSlug" type="slug" for="catTitle" suppress>
<perch:category id="desc" type="textarea" label="Description" editor="markitup" markdown 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([
'set' => 'courses',
'template' => 'course-module.html',
'filter' => [
[
'filter' => 'catPath',
'match' => 'contains',
'value' => $currentPath
],
[
'filter' => 'catParentID',
'match' => 'gt',
'value' => '0'
],
],
'each' => function($item) {
$item['lessons'] = perch_collection('lessons',[
'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_collection page, but works wherever there is a custom function – so in many official Apps, Categories and Collections.