Forum

Thread tagged as: Problem, Runway

Exclude Sub Categories For Perch Collection

I have a collection called 'Products'.

I also have a Category Set called 'Products' with categories and some sub-categories.

Some products can be assigned to a sub-category, while others just to a parent category.

How can I display products from a collection filtered just by parent category and exclude any products in sub-categories of that parent?

So to show products in a sub cat I'm doing this:

perch_collection('Products', [
      'template' => '_product_list',
      'category' => 'products/' . perch_get('cat') . '/' . perch_get('subcat'),
]);

But when I try to just filter by one category deep, it renders all products from the parent cat and sub-cat:

perch_collection('Products', [
      'template' => '_product_list',
      'category' => 'products/' . perch_get('cat') . '/',
]);

This doesn't work either:

perch_collection('Products', [
      'template' => '_product_list',
      'category' => 'products/' . perch_get('cat'),
]);

Diagnostics:

Perch Runway: 3.0.8, PHP: 5.6.30, MySQL: mysqlnd 5.0.11-dev - 20120503 - $Id: 76b08b24596e12d4553bd41fc93cccd5bac2fe7a $, with PDO
Server OS: Darwin, cgi-fcgi
Installed apps: content (3.0.8), assets (3.0.8), categories (3.0.8), perch_blog (5.5.1), perch_forms (1.9.1)
App runtimes: <?php $apps_list = [ 'perch_blog', 'perch_forms', ];
PERCH_LOGINPATH: /admin
PERCH_PATH: /Users/Toby/Sites/create-this/admin
PERCH_CORE: /Users/Toby/Sites/create-this/admin/core
PERCH_RESFILEPATH: /Users/Toby/Sites/create-this/admin/resources
Image manipulation: GD
PHP limits: Max upload 32M, Max POST 32M, Memory: 128M, Total max file upload: 32M
F1: 0c66c2e1f82f9e0b7617b2cb8270f2c7
Resource folder writeable: Yes
SCRIPT_NAME: /admin/core/settings/diagnostics/index.php
REQUEST_URI: /admin/core/settings/diagnostics/
DOCUMENT_ROOT: /Users/Toby/Sites/create-this
HTTP_HOST: ct.loc:8888
Toby Martin

Toby Martin 1 points

  • 4 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

Categories follow a cascading model, so anything in a subcategory is also in the parent category. So what you're seeing here is as correct behaviour for how the software is designed.

Can you give an example of the sort of thing you're dealing with so I can suggest a solution?

Sure, I have products that either only live in a category that is one level deep or only in subcategories of a parent category like so:

Cat A
– Products

Cat B
– Sub Cat
–– Products

It's never a mixture of the two, as in:
Cat A
– Products
–– Sub Cat
––– Products

So I thought I could do this:

if (perch_get('product')) {
    // if single product
    perch_collection('Products', [
      'filter' => 'slug',
      'match'  => 'eq',
      'value'  =>  perch_get('product'),
    ]);    
  } elseif (perch_get('subcat')) {
    perch_category('products/' . perch_get('cat') .'/' . perch_get('subcat') . '/');

    perch_collection('Products', [
      'template' => '_product_list',
      'category' => 'products/' . $catSlug . '/' . $subCatSlug,
    ]);

  } elseif (perch_get('cat')) {
    perch_category('products/' . perch_get('cat') . '/');

    perch_collection('Products', [
      'template'  => '_product_list',
      'category' => 'products/' . perch_get('cat'),
    ]);

    perch_categories([
      'set'       => 'products',
      'template'  => '_sub_category',
      'filter'    => [
        [
          'filter'  => 'catPath',
          'match'   => 'contains',
          'value'   => 'products/' . perch_get('cat')
        ],
        [
          'filter'  => 'catParentID',
          'match'   => 'neq',
          'value'   => 0
        ]
      ]
    ]);
  }

So in the last part of the if statement for top level categories with products, it would render just products knowing that perch_categories won't render anything, and vice-verser – a category with subcategories wouldn't have products, so the perch_collection function wouldn't render anything either.

Drew McLellan

Drew McLellan 2638 points
Perch Support

Right, I think I get that, but do you have a practical example? "Products, Sub Cat, Products" doesn't really make much sense to me when I don't know what those products might be.

Okay.

For reference the staging site is here:

https://ct.creativemonster.co.uk

The category 'Direct Mail' should only have subcategories with products in those subcategories, but the top-level category 'Advent Calendars & Christmas' should only have products directly in that category.

Hope that helps.

Okay.

For reference the staging site is here:

https://ct.creativemonster.co.uk

The category 'Direct Mail' should only have subcategories with products in those subcategories, but the top-level category 'Advent Calendars & Christmas' should only have products directly in that category.

Hope that helps.

Drew McLellan

Drew McLellan 2638 points
Perch Support

Ok, that seems fine. Where does the problem arise?

When I need to show only subcategories and not products.

For example the 'Direct Mail' category should only show a list of subcategories, but if I use the code above, it renders all products from any descendants of 'Direct Mail'.

Drew McLellan

Drew McLellan 2638 points
Perch Support

You'd use perch_categories() to show the subcategories, and perch_collection() when you need to show products filtered by category.

That's what I'm already doing per my above code:

} elseif (perch_get('cat')) {
      perch_category('products/' . perch_get('cat') . '/');

      perch_categories([
        'set'       => 'products',
        'template'  => '_sub_category',
        'filter'    => [
          [
            'filter'  => 'catPath',
            'match'   => 'contains',
            'value'   => 'products/' . perch_get('cat')
          ],
          [
            'filter'  => 'catParentID',
            'match'   => 'neq',
            'value'   => 0
          ]
        ]
      ]);

      perch_collection('Products', [
        'template'  => '_product_list',
        'category' => 'products/' . perch_get('cat')
      ]);
    }
  }

But the problem arises when the user visits a category page that has subcategories – it renders both subcategories and products when it should be just subcategories.

I guess I could do a count on perch_categories filtered by catPath and if it's more than 1 then just show subcategories, else show products.

Drew McLellan

Drew McLellan 2638 points
Perch Support

That sounds reasonable.