Sub Category Runway and Shop

  • Hi all

    I am having some difficulties with understanding how to achieve listing the sub-categories linked from one top category.

    What I have working so far

    1) I have all of my top level [0] only categories listed using

    Code
    1. perch_categories([
    2. 'template' => 'product-category.html',
    3. 'set' => 'products',
    4. 'filter' => 'catParentID',
    5. 'match' => 'eq',
    6. 'value' => 0,
    7. ]);

    In the template I have a link around the catTitle

    Code
    1. <a href="/category/<perch:category id="catSlug" />"><h4><perch:category id="catTitle" /></h4></a>

    2) I have a page 'category' with a route of category/[slug:cat]

    Code
    1. perch_shop_products([
    2. 'category' => 'products/'.perch_get('cat'),
    3. ]);

    This is listing any products in the category and when clicked works correctly taking you to the product page.


    What I am having difficulties with


    I also have sub-categories and so I will need another step:


    Click on a top category > displays only those sub-categories > click on a sub-category displays list of products.


    I have looked everywhere for a solution so any help would be appreciated.


    Thanks

  • Hi Colin,


    You need to have 3 different views:

    1. Top-level categories view
    2. Sub-categories view
    3. Categorised product list view


    You've already worked out (1).


    To implement (2) or (3) is a little more involved. You need to check whether the current category has any sub-categories and proceed accordingly. Here is a simplified example:



    For listing sub-categories without their parent category: https://grabapipit.com/blog/listing-sub-categories

  • Hi Hussein


    Thank you for your reply. I have been trying to get this to work with my limited PHP knowledge.


    If I hard code the $catPath = 'products/shoes/'; then I can get this to work. My knowledge falls short of being able to get the path from the top-level link so that this is a dynamic link.


    Is this possible or should I be using pages for each top-level category?


    Thanks

  • You can either set up multiple URL patterns to support a finite number of levels:

    • shop/[slug:path]
    • shop/[slug/slug:path]
    • shop/[slug/slug/slug:path]

    Or create a custom token to support infinite levels:

    • shop/[mycustomtoken:path]


    Then you can get the path and handle the rest in PHP:


  • Hi

    I now have this almost working.

    Using routes:

    sub-category/[slug:path]

    sub-category/[slug/slug:path]

    on my sub-category master page:

    So click any top level link and then…

    category (with no sub cat) > products list > the product page - working

    category (with sub cat) > subcategory list > no products listing


    I have tried using a second master page 'categorised' with the same routes and master page code but still the products are not listing.


    To test, if on the second 'categorised' page I use:

    Code
    1. perch_shop_products([
    2. 'template' => 'products/list.html',
    3. 'category' => 'products/pressure-cushions/'
    4.       // 'category' => $catPath
    5. ]);

    The products in the coded category are listing.


    I must be missing something,

    Any help appreciated.

    Thanks

  • Hi Hussein


    I do not get a PHP error, so I get the body top/bottom etc but no product list.


    The template:

    Code
    1. <perch:before><ul>product-sub-category.html</perch:before>
    2. <li style="margin-left: <perch:category id="catDepth" type="hidden" />0px;">
    3. <a href="/categorised/<perch:category id="catSlug" />"><h4><perch:category id="catTitle" /></h4></a>
    4. <img src="<perch:category id="image" type="image" label="Image" width="200" />" alt="<perch:category type="text" id="alt" label="Description"/>" />
    5. <perch:category id="desc" type="textarea" html="true"/>
    6. </li>
    7. <perch:after></ul></perch:after>
    8. <perch:noresults>
    9. Sorry, there are no items currently available.
    10. </perch:noresults>


    The debug Message:

    Thanks for any help.

  • The following returns the rendered template:


    PHP
    1. $sub_categories = perch_categories([
    2. 'template' => 'product-sub-category.html',
    3. 'filter' => 'catPath',
    4. 'match' => 'regex',
    5. 'value' => '^' . $catPath . '([a-z])+'
    6. ], true);


    So given you have perch:noresults tags in the sub-categories template, it will always return something and hence the following condition will always evaluate to true:


    PHP
    1. if($sub_categories) {
    2. }


    I would move the perch:noresults message to your product list. The logic is:


    • First display top-level categories
    • When you are on a category page, check if it has some sub-categories. If it does, display them.
    • Otherwise display the products within that category. If there is none, display the perch:noresults message


    So you never really need to display the perch:noresults message for sub-categories; only for products.

  • Hi


    Thanks for the reply and explaining the logic. I have moved the perch:noresults to the product list template.


    My results now are:

    category (with no sub cat) > products list > the product page - working

    category (with sub cat) > subcategory list > perch:noresults message (Sorry etc)

    eg: Pressure cushions > Sero Pressure Cushions > Sorry, …


    I get this for any subcategory even though there are products there.


    I am not sure what I am missing as this must be being used for any shop with sub-categories.

  • Here is the debug message


    0 recover(): "> [1] SELECT u.*, r.* FROM perch3_users u, perch3_user_roles r WHERE u.roleID=r.roleID AND u.userEnabled=1 AND u.userID=1 AND u.userHash='fa130d5b2d8da6a4a064a071485f0884' LIMIT 1
    0.0005 update(): ">UPDATE perch3_users SET userHash='a84faf51e0f3542ea298767c63ecc7f8' WHERE userID='1'
    0.0003 get_route(): "> [42] SELECT p.pagePath, pr.routePattern, pr.routeRegExp, p.pageTemplate, pr.routeOrder, s.settingValue AS siteOffline FROM perch3_pages p LEFT JOIN perch3_page_routes pr ON p.pageID=pr.pageID LEFT JOIN perch3_settings s ON s.settingID='siteOffline' UNION SELECT NULL AS pagePath, pr2.routePattern, pr2.routeRegExp, pr2.templatePath AS pageTemplate, pr2.routeOrder, NULL AS siteOffline FROM perch3_page_routes pr2 WHERE templateID!=0 ORDER BY routeOrder ASC, pagePath ASC
    0.003 get_route(): ">Matched route: categorised/[slug:path]
    0.0001 Using master page: /templates/pages/shop/products/product-categorised-master.php
    0 Page arguments:
    Code
    1. Array
    2. ( [0] => /categorised/sero-pressure-cushions [path] => sero-pressure-cushions [1] => sero-pressure-cushions
    3. )
    0.0036 find_by_path(): "> [1] SELECT * FROM perch3_pages WHERE pagePath='/categorised' LIMIT 1
    0.004 get_cart_field(): "> [1] SELECT * FROM perch3_shop_cart WHERE cartID=4573
    0.0003 get_cart_field(): "> [1] SELECT * FROM perch3_shop_cart WHERE cartID=4573
    0.0004 get_currently_active(): "> [nil] SELECT * FROM perch3_shop_sales WHERE saleFrom<='2020-03-05 11:13:00' AND saleTo>'2020-03-05 11:13:00' AND saleActive=1 AND saleDeleted IS NULL ORDER BY saleOrder ASC
    0.0005 get(): "> [63] SELECT DISTINCT settingID, settingValue FROM perch3_settings WHERE userID=0
    0.0017 template_attributes(): ">Using template: /templates/pages/attributes/default.html
    0.0001 find_all_tag_ids(): ">Using sub-template: /templates/pages/attributes/seo.html
    0 find_all_tag_ids(): ">Using sub-template: /templates/pages/attributes/facebook.html
    0 find_all_tag_ids(): ">Using sub-template: /templates/pages/attributes/twitter.html
    0.0017 __construct(): ">Using template: /templates/search/search-form-comodita.html
    0.0013 get_navigation(): "> [22] SELECT * FROM perch3_pages WHERE pageNew=0 AND pageHidden=0 AND pageDepth >=0 AND pageDepth<=3 ORDER BY pageTreePosition ASC
    0.0008 get_value(): "> [1] SELECT pageTreePosition FROM perch3_pages WHERE pagePath='/categorised' LIMIT 1
    0.0003 find_parent_page_ids_by_path(): "> [2] SELECT pageID FROM perch3_pages WHERE pageTreePosition IN ('000-004-011', '000-004', '000') ORDER BY pageTreePosition DESC
    0.0005 _template_nav(): ">Using template: /templates/navigation/top-nav-item-0.html
    0.0001 _template_nav(): ">Using template: /templates/navigation/top-nav-item-1.html
    0 _template_nav(): "> [2] Using template: /templates/navigation/top-nav-item-2.html
    0.0009 _template_nav(): "> [4] Using template: /templates/navigation/top-nav-item-1.html
    0.0027 get_value(): "> [0] SELECT setID FROM perch3_category_sets WHERE setSlug='' LIMIT 1
    0.0003 get_filtered_listing(): "> [nil] SELECT main.* FROM perch3_categories main WHERE 1=1 AND (catPath REGEXP '^products\/sero-pressure-cushions\/([a-z])+') ORDER BY catTreePosition ASC
    0.0006 get_filtered_listing(): ">Using template: /templates/categories/product-sub-category.html
    0.0006 _get_filter_sub_sql(): "> [0] SELECT DISTINCT idx.itemID FROM perch3_shop_index idx JOIN perch3_shop_products main ON idx.itemID=main.productID AND idx.itemKey='productID' AND ((idx.indexKey='_category' AND idx.indexValue LIKE 'products/sero-pressure-cushions/%' OR idx.indexKey='_category' AND idx.indexValue='products/sero-pressure-cushions/'))
    0.0008 get_filtered_listing_from_index(): "> [nil] SELECT tbl.* FROM ( SELECT idx.itemID, main.*, idx2.indexValue as sortval FROM perch3_shop_index idx JOIN perch3_shop_products main ON idx.itemID=main.productID AND idx.itemKey='productID' JOIN perch3_shop_index idx2 ON idx.itemID=idx2.itemID AND idx.itemKey='productID' AND idx2.indexKey='title' AND idx.itemID IN (NULL) WHERE 1=1 AND idx.itemID=idx2.itemID AND idx.itemKey=idx2.itemKey GROUP BY idx.itemID, idx2.indexValue, productID ) as tbl WHERE (productDeleted IS NULL AND productStatus=1 AND parentID IS NULL) GROUP BY itemID, sortval ORDER BY sortval ASC
    0.0015 set(): ">Using template: /templates/shop/products/list.html
    0.0003 Request time: 0.0751
    0 Process time: 0.0747
    0 Memory: 5.0202



    Thanks

  • The query looks up products in the category with the category path products/sero-pressure-cushions/. However, based on the screenshot and the context we're discussing it should be a sub-category: products/pressure-cushions/sero-pressure-cushions/.


    I was expecting the URL to include the parent category too with something like /products/parent-category/sub-category. Isn't this what you're after?