12

The product grid of a category page (frontend) is rendered via layout in catalog_category_view.xml.

Lets say I have a custom product collection (which I got via

ProductRepositoryInterface::getList($searchCriteria) method

in a custom block class and want to render this collection. The rendered result should be displayed as a product grid on frontend (just like any category page).

How can this be done ?

By looking into catalog_category_view.xml there are two significant lines, which are responsible for rendering a product collection:

<block class="Magento\Catalog\Block\Category\View" name="category.products" template="Magento_Catalog::category/products.phtml">
<block class="Magento\Catalog\Block\Product\ListProduct" name="category.products.list" as="product_list" template="Magento_Catalog::product/list.phtml">

How can I provide my custom product collection to these template files, so they render my collection ?

Correct me, if I am wrong on this.

This is how my block code looks like:

<?php
namespace Mod\Mod1\Block;
use Magento\Framework\View\Element\Template;
class Main extends Template
{
protected $_filterBuilder;
protected $_filterGroupArray;
protected $_filterGroupBuilder;
protected $_searchCriteriaBuilder;
protected $_productRepository;
protected $_productFactory;
protected $_list;

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
    \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
    \Magento\Framework\Api\Search\FilterGroupBuilder $filterGroupBuilder,
    \Magento\Framework\Api\FilterBuilder $filterBuilder,
    \Magento\Catalog\Model\ProductFactory $productFactory,
    array $data = [])
{
    $this->_productRepository = $productRepository;
    $this->_searchCriteriaBuilder = $searchCriteriaBuilder;
    $this->_filterGroupBuilder = $filterGroupBuilder;
    $this->_filterBuilder = $filterBuilder;
    parent::__construct($context, $data);
}

public function getLoadedProductCollection(){
    $searchCrit = $this->buildSearchCriteria('','','','','','5-',1);
    $list = $this->_productRepository->getList($searchCrit);
    return $list;
}
public function buildSearchCriteria(...){
....
return $searchCriteria;
}
}
  • Are you asking how to replace products on a category page or how to essentially have another version of the category controller? – Josh Davenport Sep 19 '17 at 15:40
  • Pagination and layer navigation never come right if you edit collection in list.phtml or corresponding block. So make sure the answer you're accepting does both of the things above.Regards. – Vivek Kumar Sep 22 '17 at 7:22
0

You can try this:

Update your catalog_category_view.xml

<block class="Magento\Catalog\Block\Product\ListProduct" name="category.products.list" as="product_list" template="Magento_Catalog::product/list.phtml">
<block class="Your(Mod)\Namespace(Mod1)\Block\YourBlockFileName(Main)" name="your.category.products.list" template="Magento_Catalog::product/yourFile.phtml" />
</block>

And call yourFile.phtml in product/list.phtml:

<?php echo $this->getChildHtml('your.category.products.list'); ?>

Now, you can use your function in yourfile.phtml like this:

$block->yourfunction();

Example:

$block->getLoadedProductCollection();

Hope this can help you.

0

The best approach would be:

Update your catalog_category_view.xml and replace Magento\Catalog\Block\Product\ListProduct with Mod\Mod1\Block\Main

before:

<block class="Magento\Catalog\Block\Product\ListProduct" name="category.products.list" as="product_list" template="Magento_Catalog::product/list.phtml">

after:

block class="Mod\Mod1\Block\Main" name="category.products.list" as="product_list" template="Magento_Catalog::product/list.phtml">

Your Main class MUST extend Magento\Catalog\Block\Product\ListProduct

Then you will need to rewrite the method getLayer() to your own.

FYI: your class Mod\Mod1\Block\Main needs some refactoring.

Create your own new Layer class that will extend Magento\Catalog\Model\Layer and play around with the collections.

/**
 * Retrieve current layer product collection
 *
 * @return \Magento\Catalog\Model\ResourceModel\Product\Collection
 */
public function getProductCollection()

and

/**
 * Initialize product collection
 *
 * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
 * @return \Magento\Catalog\Model\Layer
 */
public function prepareProductCollection($collection)
0

Basically initially you want to create a controller or even a basic CMS page so you have a page to show your collection.

From there you can use your custom block which creates your collection combined with the list.phtml template file to render the products on your page.

{{block class="Vendor\Module\Block\ProductCollection" template="Magento_Catalog::product/list.phtml" name="specialproducts"}} 

Add above xml where Vendor\Module\Block\ProductCollection is the custom block code where your collection is created to xml for that page.

The list.phtml file gathers the collection from your block with below line of code:

$_productCollection = $block->getLoadedProductCollection();

So long as your block has the getLoadedProductCollection() function returning your collection of products the list.phtml file will then loop through each product in your collection rendering them in a default Magento product grid.

For your block code try updating below line to include getItems():

$list = $this->_productRepository->getList($searchCrit)->getItems();
  • I did as you said. My block has the ' getLoadedProductCollection()' function which returns 'ProductRepositoryInterface::getList()'. But I get an Error : Uncaught Error: Call to undefined method Magento\Framework\Api\SearchResults::count() in ... Looks like this is not the right approach. – shahir hajir Sep 21 '17 at 14:09
  • see updated post – shahir hajir Sep 21 '17 at 14:59
  • Maybe try changing $list = $this->_productRepository->getList($searchCrit)->getItems(); – harri Sep 21 '17 at 15:40
  • @shahirhajir Did you try with getItems? – harri Sep 25 '17 at 13:20
  • Not working. $list = $this->_productRepository->getList($searchCrit)->getItems(); returns ProductInterface[] array and this array has no count() funtion. Uncaught Error: Call to a member function count() on array in ...\list.phtml on line 22. On line 22 in list.phtml we have: $_productCollection->count() – shahir hajir Sep 25 '17 at 20:46
-1

You can render product collection in your phtml file like this

$product_collection = $block->getLoadedProductCollection();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.