Magento – Fatal error: Uncaught Error: Call to a member function setProductCollection() on boolean in

magento2productproduct-collection

( ! ) Fatal error: Uncaught Error: Call to a member function setProductCollection() on boolean in /var/www/html/magento2/ShopQuary/app/code/MagentoCoders/Manufacturer/Controller/Index/Index.php on line 60

If Anyone has seen this type of error before Please help me. I have found this error when i am Using product list template with my own product collection.

I got the reference from the below URL, I applied the same code.

Use product list template with my own product collection?

<?php

namespace MagentoCoders\Manufacturer\Controller\Index;

use MagentoCoders\Manufacturer\Block\Product\ManufacturerList;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Index extends Action
{
    /** @var PageFactory */
    protected $pageFactory;

    /** @var  \Magento\Catalog\Model\ResourceModel\Product\Collection */
    protected $productCollection;

    public function __construct(
        Context $context,
        PageFactory $pageFactory,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory
    )
    {
        $this->pageFactory = $pageFactory;
        $this->productCollection = $collectionFactory->create();
        parent::__construct($context);
    }

    protected function _prepareLayout()
    {

        return parent::_prepareLayout();
    }

    public function execute()
    {
        $result = $this->pageFactory->create();

        // obtain product collection.
        $this->productCollection->addIdFilter(5); // do some filtering
        $this->productCollection->addFieldToSelect('*');

        // get the custom list block and add our collection to it
        /** @var CustomList $list */
        $list = $result->getLayout()->getBlock('custom.products.list');
        $list->setProductCollection($this->productCollection);

        return $result;
    }
}

Block is

namespace MagentoCoders\Manufacturer\Block\Product;

use Magento\Catalog\Block\Product\ListProduct;
use Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection;

class ManufacturerList extends ListProduct
{
    public function getLoadedProductCollection()
    {
        return $this->_productCollection;
    }

    public function setProductCollection(AbstractCollection $collection)
    {
        $this->_productCollection = $collection;
    }
}

xml file

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <title>Products</title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="MagentoCoders\Manufacturer\Block\Product\ManufacturerList" name="custom.products.list" as="product_list" template="Magento_Catalog::product/list.phtml">
                <container name="category.product.list.additional" as="additional" />
                <block class="Magento\Framework\View\Element\RendererList" name="category.product.type.details.renderers" as="details.renderers">
                    <block class="Magento\Framework\View\Element\Template" as="default"/>
                </block>
                <block class="Magento\Catalog\Block\Product\ProductList\Item\Container" name="category.product.addto" as="addto">
                    <block class="Magento\Catalog\Block\Product\ProductList\Item\AddTo\Compare"
                           name="category.product.addto.compare" as="compare"
                           template="Magento_Catalog::product/list/addto/compare.phtml"/>
                </block>
                <block class="Magento\Catalog\Block\Product\ProductList\Toolbar" name="product_list_toolbar" template="Magento_Catalog::product/list/toolbar.phtml">
                    <block class="Magento\Theme\Block\Html\Pager" name="product_list_toolbar_pager"/>

                </block>
                <action method="setToolbarBlockName">
                    <argument name="name" xsi:type="string">product_list_toolbar</argument>
                </action>
            </block>
        </referenceContainer>
    </body>
</page>

Best Answer

You have to load the Layout first, before you can get the block. Anyway you can use $this->_view (set in parent) for accessing the Layout instead of creating the $result object.

Try this code for your execute() method in controller:

public function execute()
{
    // obtain product collection.
    $this->productCollection->addIdFilter(5); // do some filtering
    $this->productCollection->addFieldToSelect('*');

    // get the custom list block and add our collection to it
    /** @var CustomList $list */
    $this->_view->loadLayout();
    $list = $this->_view->getLayout()->getBlock('custom.products.list');
    $list->setProductCollection($this->productCollection);

    return $result;
}

I hope that helps.