5

How can I call a widget that displays product from a specific category in a phtml file?

Currently I can only display "all_products" in my phtml file like that:

echo $this->getLayout()->createBlock("Magento\Catalog\Block\Product\Widget\NewWidget")->setDisplayType("all_products")->setProductsCount("5")->setTemplate("product/widget/new/content/new_grid.phtml")->toHtml();

How to do this with products from specific category and not all products?

  • Why does it have to be a widget? Can't you just create a regular custom block which will prepare products collection according to your needs? – Zefiryn Apr 19 '17 at 22:22
6

There is a widget for arbitrary product lists (as mentioned by @Nits). If you insert the widget on any CMS page or block and turn off the WYSIWYG editor ("Hide editor" button), you can see how the parameters look like.

For example, I created the widget with the condition "category = 4", showing five products:

{{widget type="Magento\CatalogWidget\Block\Product\ProductsList" title="My products" products_count="5" template="product/widget/content/grid.phtml" conditions_encoded="a:2:[i:1;a:4:[s:4:`type`;s:50:`Magento|CatalogWidget|Model|Rule|Condition|Combine`;s:10:`aggregator`;s:3:`all`;s:5:`value`;s:1:`1`;s:9:`new_child`;s:0:``;]s:4:`1--1`;a:4:[s:4:`type`;s:50:`Magento|CatalogWidget|Model|Rule|Condition|Product`;s:9:`attribute`;s:12:`category_ids`;s:8:`operator`;s:2:`==`;s:5:`value`;s:1:`4`;]]"}}

From that you can see that the class is Magento\CatalogWidget\Block\Product\ProductsList and you can create it programmatically as follows:

$productsBlock = $this->getLayout()->createBlock(\Magento\CatalogWidget\Block\Product\ProductsList::class);
$productsBlock->setTitle("My products");
$productsBlock->setProductsCount(5);
$productsBlock->setTemplate("product/widget/content/grid.phtml");
$productsBlock->setConditionsEncoded("a:2:[i:1;a:4:[s:4:`type`;s:50:`Magento|CatalogWidget|Model|Rule|Condition|Combine`;s:10:`aggregator`;s:3:`all`;s:5:`value`;s:1:`1`;s:9:`new_child`;s:0:``;]s:4:`1--1`;a:4:[s:4:`type`;s:50:`Magento|CatalogWidget|Model|Rule|Condition|Product`;s:9:`attribute`;s:12:`category_ids`;s:8:`operator`;s:2:`==`;s:5:`value`;s:1:`4`;]]");

But "conditions_encoded" is a serialized array (with some characters replaced for WYSIWYG compatibility). This serialized array is difficult to construct manually, but luckily you can also use "conditions" with the unserialized value instead in PHP code. So you can replace the last line from above with:

$productsBlock->setConditions(
    [
        1 => [
            'type' => \Magento\CatalogWidget\Model\Rule\Condition\Combine::class,
            'aggregator' => 'all',
            'value' => '1',
            'new_child' => '',
        ],
        '1-1' => [
            'type' => \Magento\CatalogWidget\Model\Rule\Condition\Product::class,
            'attribute' => 'category_ids',
            'operator' => '==',
            'value' => '4',
        ]
    ]
);

Then output:

echo $productsBlock->toHtml();
  • Thank you. I did exactly what you said but got an error "Parse error: syntax error, unexpected '$productsBlock' (T_VARIABLE)" on line where "$productsBlock->setConditions(" is. – N1njaWTF Apr 28 '17 at 11:56
  • You probably figured it out yourself by taking a second look, but I forgot to add a closing bracket and semicolon after $productsBlock->setTemplate("product/widget/content/grid.phtml" - sorry for not giving you everything ready to copy and paste, I wrote the code from top of my head. – Fabian Schmengler Apr 28 '17 at 12:55
  • Thanks for the correction. The code with the "unserialized value" returns "We're sorry, an error has occurred while generating this email." The serialized one works tho :) thanks! – N1njaWTF Apr 28 '17 at 13:54
  • This for some reason does not filter products by category but returns all products – CompactCode Sep 30 '17 at 20:40
  • @SwAt.Be if you used the serialized value from my code, try following the manual steps to retrieve it by yourself. I think, the serialization format has been changed in the latest Magento versions. – Fabian Schmengler Oct 2 '17 at 6:08
5
+25

You can do it via static-block: 1) add static block with widget of catalog product list and add category id in widget condition. (content menu >> Blocks >> add new >> click on show/hid button >> insert widget >> select catalog product list from widget type >> add title >> select category in condition field (click on + icon) >> insert widget >> save this block. 2) you can call this block in phtml file as well as xml file.

<?php echo $block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('block_identifier')->toHtml();?>

OR XML

<block class="Magento\Cms\Block\Block" name="Promo">
    <arguments>
        <argument name="block_id" xsi:type="string">promo</argument>
    </arguments>
</block>

I Hope this will help you.

  • Thanks. Good answer and works. But isnt there a way without creating an additional block and calling that widget directly in the phtml? – N1njaWTF Apr 21 '17 at 11:50
0

If you can't do it via static block, then you should create a new module for handling category in product widget.

See code sample here ( This will show new products from specific category ).

<?php
/**
 *
 * @category    Jworks
 * @package     Jworks_ProductWidget
 * @author Jitheesh V O <jitheeshvo@gmail.com>
 */
namespace Jworks\ProductWidget\Block\Widget;

/**
 * New products widget
 */
class CategoryWidget extends \Magento\Catalog\Block\Product\Widget\NewWidget implements \Magento\Widget\Block\BlockInterface
{
    const DISPLAY_TYPE_CATEGORY_PRODUCTS = 'category_products';
    /**
     * @var \Magento\Catalog\Model\CategoryFactory $categoryFactory
     */
    protected $_categoryFactory;

    /**
     * @param \Magento\Catalog\Block\Product\Context $context
     * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory
     * @param array $data
     */
    public function __construct(
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
        \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility,
        \Magento\Framework\App\Http\Context $httpContext,
        array $data = []
    )
    {
        $this->_categoryFactory = $categoryFactory;
        parent::__construct(
            $context,
            $productCollectionFactory,
            $catalogProductVisibility,
            $httpContext,
            $data
        );
    }

    /**
     * Product collection initialize process
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Collection|Object|\Magento\Framework\Data\Collection
     */
    protected function _getProductCollection()
    {
        switch ($this->getDisplayType()) {
            case self::DISPLAY_TYPE_CATEGORY_PRODUCTS:
                $collection = $this->_getCategoryProductCollection();
                break;
            default:
                $collection = parent::_getProductCollection();
                break;
        }
        return $collection;
    }

    /**
     * @return $this|\Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    protected function _getCategoryProductCollection()
    {
        $collection = $this->_productCollectionFactory->create();
        $collection->setVisibility($this->_catalogProductVisibility->getVisibleInCatalogIds());
        $categoryId = $this->getCategoryId();

        $category = $this->_categoryFactory->create()->load($categoryId);
        $collection = $collection->addCategoryFilter($category);
        $collection = $this->_addProductAttributesAndPrices($collection)
            ->addStoreFilter()
            ->addAttributeToSort('created_at', 'desc')
            ->setPageSize($this->getPageSize())
            ->setCurPage($this->getCurrentPage());
        return $collection;
    }

    /**
     * Retrieve category id
     *
     * @return int
     */
    public function getCategoryId()
    {
        if (!$this->hasData('category_id')) {
            return $this->_storeManager->getStore()->getRootCategoryId();
        }
        return $this->getData('category_id');
    }
}

You can call this widget by using following code in phtml files

<?php echo $this->getLayout()->createBlock("Jworks\ProductWidget\Block\Widget\CategoryWidget")->setDisplayType("category_products")->setCategoryId(5)->setProductsCount("5")->setTemplate("product/widget/category/new_grid.phtml")->toHtml(); ?>

See my sample extension here

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.