Forum

Thread tagged as: Question, Problem

Output subcategories associated to parent

I've read through all the various threads relating to this but still cant get it to work. I'm trying to output a list of parent categories as a nav, then when the parent category is selected output the subcategories of that parent. I have it very nearly working using this:

 $categories = perch_categories([
        'set' => 'departments',
        'template' => 'categories-nav.html',
      ]);

      $categories = perch_categories([
        'set' => 'departments',
        'template' => 'categories-sub-nav.html',
      ]);

That outputs all of the parent categories and all of the subcategories. If I add a filter to it none of the subcategories are displayed:

'filter' => 'catPath',
        'match' => 'contains',
        'value' => perch_get('cat')

How can I output just the subcategories for the selected parent?

categories-nav.html:

<perch:before>
  <ul class="categories__nav">
</perch:before>

  <perch:if id="catDepth" value="1">

    <li class="category__nav">
      <a href="/crew/<perch:category id="catPath">" class="category__nav__link">
        <perch:category id="catTitle" />
      </a>
    </li>

  </perch:if>

<perch:after>
  </ul>
</perch:after>

categories-sub-nav.html:

<perch:before>
  <ul class="categories__nav categories__nav--sub">
</perch:before>

    <perch:if id="catParentID" match="gt" value="0">

      <li class="category__nav__item">
        <a href="/crew/<perch:category id="catPath">" class="category--nav__link">
          <perch:category id="catTitle" />
        </a>
      </li>

    </perch:if>


<perch:after>
  </ul>
</perch:after>
Rob Saunders

Rob Saunders 0 points

  • 3 years ago

Along the same lines how do you test for a subcategory as well as a parent category. I would like to add a selected class to the parent when selected, I have done this as normal using:

<perch:if id="catPath" match="eq" value="{current_category}" />

However the catPath when a sub category is selected has an addiotional field in the URL and there is no match. I would like the parent category to stay selected. I assumed match="contains" would work here but it throws an error:

Warning: preg_match(): Unknown modifier 'c' in /Users/Rob/Sites/bristolcrew/build/admin/core/lib/PerchTemplate.class.php

Any pointers with this? Surely there must be a simple solution, its standard nested navigation.

I've got a bit closer by removing the trailing slash from perch_get('cat'):

 <?php

        $catPath = substr(perch_get('cat'), 0, -1); //Remove trailing slash for sub nav filtering
        PerchSystem::set_var('current_category', perch_get('cat'));

        perch_categories([ //Top level
          'set' => 'departments',
          'template' => 'categories-nav.html',
          'filter' => 'catParentID',
          'value' => 0,
          'match' => 'eq'
        ]);
          perch_categories([ //Sub level
            'set' => 'departments',
            'template' => 'categories-sub-nav.html',
            'filter' => 'catPath',
            'match' => 'contains',
            'value' => $catPath
          ]);
      ?>

For some reason this works which I dont understand because perch_get and the catPath both seem to have trailing slashes. But the match wouldnt work without removing it so...!? This at least filters down the subcategory to the current path but then when selecting a subcategory it the only displays that one subcategory rather than the full list underneath the parent.

I'm also still having no luck with any match="contains" on templates, any suggestions as to why this would be? Just throws the above error.

Any chance of some support with this? Is there anywhere else to find support?

Managed to get a bit further. I've got the current parent category by taking the URL and stripping off anything after the 2nd occurrence of "/". Then filtering the sub category on this. Feels like a bit of a hack but its working. However I still cant set the current category based on this as match="contains" doesn't seem to work within a template...still returning the above error.

if (perch_get('cat')) {
         $currentCat = perch_get('cat');
          $currentParentCat = substr($currentCat, 0, strpos($currentCat, '/', strpos($currentCat, '/')+1)); //Get Parent Category
          PerchSystem::set_var('current_parent_category', $currentParentCat);

          perch_categories([ //Top level
            'set' => 'departments',
            'template' => 'categories-nav.html',
            'filter' => 'catParentID',
            'value' => 0,
            'match' => 'eq'
          ]);

          perch_categories([ //Sub level
            'set' => 'departments',
            'template' => 'categories-sub-nav.html',
            'filter' => 'catPath',
            'match' => 'contains',
            'value' => $currentParentCat
          ]);

        }
Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

Hello Rob,

I've got the current parent category by taking the URL and stripping off anything after the 2nd occurrence of "/". Then filtering the sub category on this. Feels like a bit of a hack but its working.

Are you on regular Perch or Runway? If you are using Runway, you can use routes

However I still cant set the current category based on this as match="contains" doesn't seem to work within a template...still returning the above error.

Try hardcoding the value and see if that works. If it does, work on getting the value dynamically in the same format.


Any chance of some support with this? Is there anywhere else to find support?

For official support you are in the right place. For community support you can get some here or on the Perchology Slack group: https://perchology.slack.com

Thanks Hussain, that pointed me in the right direction which helped. I'm on standard Perch so no routes for this one. I finally got it all working by pulling apart the URL into its different sections for full catPath, parent category, sub category. It seems that match="contains" wont work if there are any / characters in the value being tested so I had to pull all those out of the variables too. Here's my final code in case it is useful for anyone else: listing-page.php:

 //Variables
  $currentCat = perch_get('cat');
  $currentParentCat = substr($currentCat, 0, strpos($currentCat, '/', strpos($currentCat, '/')+1)); //Get Parent Category
  $currentMidCat = str_replace('departments/', '', $currentParentCat); //Get parent category without the set
  $subCat = implode('/', array_slice( explode( '/', $currentCat ),2 )); //Get sub category without parent or set.
  $currentSubCat = str_replace('/', '', $subCat); //Remove trailing slash because?!?!
  PerchSystem::set_var('current_category', $currentCat);
  PerchSystem::set_var('current_sub_category', $currentSubCat);
  PerchSystem::set_var('current_mid_category', $currentMidCat);
  PerchSystem::set_var('current_parent_category', $currentParentCat);

        if (perch_get('cat')) {

          perch_categories([ //Top level
            'set' => 'departments',
            'template' => 'categories-nav.html',
          ]);

          perch_categories([ //Sub level
            'set' => 'departments',
            'template' => 'categories-sub-nav.html',
            'filter' => 'catPath',
            'match' => 'contains',
            'value' => $currentParentCat
          ]);

        } else {

          perch_categories([ //Top level
            'set' => 'departments',
            'template' => 'categories-nav.html',
            'filter' => 'catParentID',
            'value' => 0,
            'match' => 'eq'
          ]);

          perch_categories([ //Sub level
            'set' => 'departments',
            'template' => 'categories-sub-nav-blank.html',
          ]);

        }

categories-nav.html:

<perch:before>
  <ul class="categories__list">
    <li class="categories__list__item categories__list__item--logo">
      <a href="/">
        <img src="/a/img/bristol-crew-logo.png" alt="Bristol Crew Logo" />
      </a>
    </li>
</perch:before>

      <perch:if id="catParentID" match="eq" value="0">
        <li class="categories__list__item <perch:if id="catPath" match="contains" value="{current_mid_category}" />selected</perch:if>">
          <a href="/crew/<perch:category id="catPath">" class="categories__list__item__link">
            <perch:category id="catTitle" />
          </a>
        </li>
      </perch:if>

<perch:after>
  </ul>
</perch:after>

categories-sub-nav.html:

<perch:before>
  <ul class="categories__list categories__list--sub">
</perch:before>

    <perch:if id="catParentID" match="gt" value="0">

      <li class="categories__list__item <perch:if exists="current_sub_category"><perch:if id="catPath" match="contains" value="{current_sub_category}" />selected</perch:if></perch:if>">
        <a href="/crew/<perch:category id="catPath">" class="categories__list__item__link categories__list__item__link--sub">
          <perch:category id="catTitle" />s
        </a>
      </li>

    </perch:if>

<perch:after>
  </ul>
</perch:after>