Silverstripe - show products from parent category and subcategory

123 Views Asked by At

I have problem when i try to loop all products from parent category and its sub-catgories.

I create two extra page types:

  1. ProductCategory
  2. Product

In SiteTree (pages) i create structure:

 |-Pages
    |- Dental equipment (productCategory)
           |----- Sub category (productCategory)
                      |----- Sub sub category (productCategory)
                                    |----- Sub sub sub category (productCategory)
                                           |----- Product 1 (product type)
                                           |----- Product 2 (product type)
                                           |----- Product 3 (product type)
                                           |----- Product 4 (product type)

Now in ProductCategory_Controller i create method to loop all products that not working.

 public function Products()
    {

        $products = Product::get()->filter([
            'ParentID' => $this->ID
        ]);

        return  $products;
    }

My question is how to get all products thats belongs to all parenet and sub-categories?

2

There are 2 best solutions below

0
Conny Nyman On

If you're trying to get the products for the current category page and all parent category pages, then the example code below might point you in the right direction.

If I misunderstood your question, please comment and I'll update my answer.

<?php

namespace {
    class ProductCategoryPageController extends PageController
    {
        public function ProductsInCurrentPageTree()
        {
            $currentPage = $this->data();
            $parentPage = $currentPage->getParent();
            if (!$parentPage) {
                // No parent page, return the current page products
                return ProductPage::get()->filter('ParentID', $currentPage->ID);
            }

            $pageTreeIds = [
                $currentPage->ID,
                $parentPage->ID,
            ];

            while ($parentPage = $parentPage->getParent()) {
                // Any conditions to break out of the loop, for instance, if your category/product pages does not start from the root level
                if (!$parentPage instanceof ProductCategoryPage) {
                    break;
                }
                $pageTreeIds[] = $parentPage->ID;
            }
            
            return ProductPage::get()->filterAny(['ParentID' => $pageTreeIds]);
        }
    }
}
0
Barry On

Recursively call the same function for child category pages, but when no children, then add products to an array list. Untested code, but should be clear enough:

class ProductCategoryPageController extends PageController {

    public function ProductsRecursive($iParentID,$productList) {
        $productCategoryPages = ProductCategoryPage::get()->filter(['ParentID' => $iParentID]);
        if ($productCategoryPages) {
            //assuming product category pages only have children and no products themselves
            foreach ($productCategoryPages as $productCategoryPage) 
                $productList = $this->ProductsRecursive($productCategoryPage->ID,$productList);
        }
        else {
            //assuming you only are collecting product pages that have no children
            foreach (ProductPage::get()->filter(['ParentID' => $iParentID]) as $productPage)
                $productList->push($productPage);
        }
        return $productList;
    }

    public function Products() {
        return $this->ProductsRecursive($this->ID, ArrayList::create());
    }
}