Forum

Thread tagged as: Question, Problem, Runway

Iterative loop with Collections?

I have a "master" Collection called "Properties" and another Collection called "Localities". In Perch admin I've related related each Property to a particular Locality. The site structure looks like this:

Home
_Locality A ("Metropolis")
__Property 1
__Property 2
_Locality B ("Gotham")
__Property 3
__Property 4
etc.

On my home page, I need to build a navigational section that looks like this:

<perch:before>
<h3><perch:related id="parent_locality" collection="Localities"><a href="/<perch:content id="locality_slug" type="slug" />/"><perch:content id="locality_name" type="text" /></a></h3></perch:related>
<ul >
</perch:before>
<li><a href="/<perch:related id="parent_locality" collection="Localities"><perch:content id="locality_slug" type="slug" /></perch:related>/<perch:content id="property_slug" />/"><perch:content id="property_name" type="text" /></a></li>
<perch:after>
</ul>
</perch:after>

I can get the above template to work if I hard-code one filter value (e.g., "metropolis") in my home.php layout:

  perch_collection('Properties', [
    'template' => 'home-our-centers.html',
    'filter' => 'parent_locality.locality_slug',
    'match' => 'eq',
    'value' => 'metropolis',
    'sort' => 'parent_locality.locality_sort',
    'sort-order' => 'ASC',
  ]);

But of course what I really want is to repeat that pattern for each related Locality dynamically.

How do I iteratively loop that perch_collection and insert the locality_slug as the filter match value for each related Locality?

I apologize for my weak PHP-fu and thank you for your assistance!

Joel Davies

Joel Davies 0 points

  • 4 years ago
Rachel Andrew

Rachel Andrew 394 points
Perch Support

You probably need to use a callback function, there is an example here https://docs.grabaperch.com/runway/collections/callback-functions-with-each/

Thanks, Rachel. After some flailing I have a callback function going the way I need. My initial struggles were partly due to the fact that the callback function examples in the documentation involve Category structures, which I'm not using in my solution, but which became extra chaff that confused my brain.

To assist other folks similarly challenged by callback functions, I thought I'd post my solution:

I ended up with this in my home.php file

perch_collection('Localities', [
  'template' => 'home-our-centers-cbf.html',
  'filter' => 'locality_slug',
  'match' => 'neq',
  'value' => 'locality-were-excluding',
  'sort' => 'locality_sort',
  'sort-order' => 'ASC',
  'each' => function($item) {
    $item['oc_loc_properties'] = perch_collection('Properties', array(
      'template' => 'oc-loc-properties.html',
      'filter' => 'parent_locality.locality_slug',
      'match' => 'eq',
      'value' => $item['locality_slug'],
    ),true);
    return $item;
  },
]);

Template home-our-centers-cbf.htm (stripped to essentials):

<perch:before>
  <div class="our-shopping-centers-grid">
</perch:before>
    <div>
      <h3><a href="/<perch:content id="locality_slug" type="slug" />/"><perch:content id="locality_name" type="text" /></a></h3>
      <ul class="menu vertical">
        <perch:content id="oc_loc_properties" hidden="true" encode="false" />
      </ul>
    </div>
    <perch:after>
  </div>
</perch:after>

Template oc-loc-properties.html (stripped to essentials):

<li><a href="/<perch:related id="parent_locality" collection="Localities"><perch:content id="locality_slug" type="slug" /></perch:related>/<perch:content id="property_slug" />/"><perch:content id="property_name" type="text" /></a></li>

So, in all my staring at callback functions examples, the part I had the most trouble with was the pattern $item['some_id'].

Took me a while to realize that the brackets mean we are targeting the the array of named IDs that reside in the our initial Collection template ('home-our-centers.cbf.html').

So, in English, the PHP is saying...

Loop through our filtered set of Localities applying the 'home-our-centers.cbf.html' template, AND, each time you do, in that template's 'oc_loc_properties' tag, return a related set of Properties, filtered to match the Locality and displayed using this secondary template "oc-loc-properties.html"

If wiser heads spot a mistake there, feel free to offer correction!

Drew McLellan

Drew McLellan 2638 points
Perch Support

What problem are you now having?

No problems, Drew, just wanted to document the solution for others.