How can I retrieve a product collection by a root category and from all its subcategories?
Eg:
Root Category (2 products)
- Subcategory 1 (2 products)
- Subcategory 2 (3 products)
So I want to retrieve all 7 products in the collection.
You can use like this:
/** \Magento\Catalog\Api\CategoryRepositoryInterface */
protected $categoryRepository;
/** \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory */
protected $productCollectionFactory;
public function getAllProductOfSubcategories($categoryId, $storeId = null) {
/** @var $result \Magento\Catalog\Model\ResourceModel\Product\Collection */
$result = $this->productCollectionFactory->create();
//get category at $storeId
try {
$category = $this->categoryRepository->get($categoryId, $storeId);
} catch (\Magento\Framework\Exception\NoSuchEntityException $noSuchEntityException) {
return null;
}
return $result->addCategoryFilter($category);
}
*Note: Your category must Enable Anchor
*Note: run php bin/magento indexer:reindex
just for make sure
Code for your class file:
protected $_categoryHelper;
protected $_categoryRepository;
public function __construct(
\Magento\Catalog\Helper\Category $categoryHelper,
\Magento\Catalog\Model\CategoryRepository $categoryRepository,
array $data = []
)
{
$this->_categoryHelper = $categoryHelper;
$this->_categoryCategoryRepository = $categoryRepository;
parent::__construct($context, $data);
}
public function getStoreCategories()
{
return $this->_categoryHelper->getStoreCategories();
}
public function getCategory($categoryId)
{
return $this->_categoryRepository->get($categoryId);
}
Code for your template file:
$categories = $block->getStoreCategories();
foreach ($categories as $category) {
echo $category->getName();
echo ' ( ' . $category->getProductCount() . ' )';
$subCategories = $block->getCategory($category->getId());
foreach ($subCategories as $subCategory) {
echo $subCategory->getName();
echo ' ( ' . $subCategory->getProductCount() . ' )';
}
}
Source: Magento 2: Get parent category, children categories & product count
I solved it as below,
protected $_category;
protected $_productCollection;
/** You should provide your root category here, and it will return comma seperated sub category list */
public function getChildren($categoryId = false)
{
if ($this->_category) {
return $this->_category->getChildren();
} else {
return $this->getCategory($categoryId)->getChildren();
}
}
protected function _getProductCollection()
{
$childListStr = $this->getChildren( 2 ); // Provide the root category ID
$childList = explode( ",", $childListStr );
$catToLoad = array();
foreach( $childList as $item ){
array_push( $catToLoad, $item );
}
if ($this->_productCollection === null) {
$layer = $this->getLayer();
$this->_productCollection = $layer->getProductCollection();
}
$this->_productCollection->addCategoriesFilter(['in' => $catToLoad ]);
return $this->_productCollection;
}
Hi I have another way to get product collection from root category... check it out.. I hope this help
public function __construct(
\Magento\Catalog\Model\Layer\Category $categoryLayer
){
$this->_categoryLayer = $categoryLayer;
}
public function getProductCollection($category){
return $this->_categoryLayer->setCurrentCategory($category)->getProductCollection();
}
Try this
$category = Mage::getModel('catalog/category')->load(2);
$children = Mage::getModel('catalog/category')->getCollection()->setStoreId(Mage::app()->getStore()->getId());
$children->addAttributeToSelect('*')
->addAttributeToFilter('parent_id', $category->getId())
->addAttributeToFilter('is_active', 1)
->addAttributeToSort('position');
foreach($children as $child)
{
$category=Mage::getModel('catalog/category')->load($child->entity_id);
}