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
    Commented Apr 19, 2017 at 22:22

3 Answers 3


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");

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:

        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
    Commented Apr 28, 2017 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. Commented Apr 28, 2017 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
    Commented Apr 28, 2017 at 13:54
  • This for some reason does not filter products by category but returns all products Commented Sep 30, 2017 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. Commented Oct 2, 2017 at 6:08

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();?>


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

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
    Commented Apr 21, 2017 at 11:50

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 ).

 * @category    Jworks
 * @package     Jworks_ProductWidget
 * @author Jitheesh V O <[email protected]>
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;

     * 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();
                $collection = parent::_getProductCollection();
        return $collection;

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

        $category = $this->_categoryFactory->create()->load($categoryId);
        $collection = $collection->addCategoryFilter($category);
        $collection = $this->_addProductAttributesAndPrices($collection)
            ->addAttributeToSort('created_at', 'desc')
        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 and acknowledge you have read our privacy policy.

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