I have a custom phtml file which I am calling on a page, and I would like to display the products from the site in this block. I'm doing a migration from m1 and in the original file the following code was used:

$products = Mage::getModel('catalog/category')->load(4)
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4);

I have seen using a block is the best way to go, avoiding object manager, such as the following:

use Magento\Catalog\Model\ProductFactory;
use Magento\Framework\View\Element\Template\Context;

protected $_productFactory;

public function __construct(
   Context $context, 
   ProductFactory $productFactory,
   array $data = array()       
) {
   $this->_productFactory   = $productFactory;
   parent::__construct($context, $data);

public function getProductCollection() {
   $productCollection = $this->_productFactory->create()->getCollection();
   return $productCollection;

However I don't know how to add a block to a theme, only an extension/module.

Can you add a block to a theme or do I need to make an extension just to allow products? If it is possible how does the structure for the theme then work?


(Note just using Vendor as an example) I created a new extension in:


I created a new class of ProductDisplay in


I created a new templated in


I'm calling it in my cms page with:

{{block class="Vendor\Productdisplay\Block\ProductDisplay"  template="Vendor_ProductDisplay::productdisplay.phtml"}}
  • You will need a template file first to call these functions and render the data in html. Then you can call this block with template file on a cms page. Have you got the template file ready?
    – harri
    Jun 14, 2017 at 12:46
  • Yes I already have a template file in place, being called by a cms page. It displays as expected.
    – Aravona
    Jun 14, 2017 at 12:48
  • So this block you have created will need to be in a module. Then you can call like below {{block class="Vendor\Module\Block\CustomProducts" template=customproducts.phtml"}}
    – harri
    Jun 14, 2017 at 12:49
  • Ok, but where do I create the block?
    – Aravona
    Jun 14, 2017 at 12:49
  • Vendor\Module\Block\CustomProducts.php
    – harri
    Jun 14, 2017 at 12:50

1 Answer 1


You will need to create a module / extension.

See here but skip controller and just follow make a block where you will use your code stated in question:


You can also skip the layout section if you are going to call this from a CMS page with code like below:

 {{block class="Vendor\ProductDisplay\Block\CustomProducts" category_id="4" name="customproducts" template="Vendor_ProductDisplay::customproducts.phtml"}}

OR by adding below to layout xml in design tab of CMS Page

<referenceContainer name="content">
    <block class="Vendor\ProductDisplay\Block\CustomProducts" template="Vendor_ProductDisplay::customproducts.phtml" name="customproducts">

So create a block named CustomProducts.php like below within Vendor/Customproducts/Block folder:

namespace Vendor\ProductDisplay\Block;

use Magento\Catalog\Model\ProductFactory;
use Magento\Framework\View\Element\Template\Context;

class CustomProducts {

protected $categoryFactory;
protected $_objectManager = null;
protected $_categoryFactory;
protected $_category;
protected $_productCollectionFactory;

public function __construct(
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Framework\ObjectManagerInterface $objectManager,
\Magento\Catalog\Model\CategoryFactory $categoryFactory
) {
$this->_productCollectionFactory = $productCollectionFactory;
$this->_objectManager = $objectManager;
$this->_categoryFactory = $categoryFactory;
public function getCategory()
$categoryId = $this->getCategoryId();
$category = $this->categoryFactory->create()->load($categoryId);
return $category;
public function getProductCollection() {
   $productCollection = $this->_productFactory->create()->getCollection();
   return $productCollection;

Then your template file customproducts.phtml should be stored within Vendor/Customproducts/view/frontend/templates

Example of template:

Then you can use in the template this:

<?php foreach ($block->getProductCollection() as $product) : ?>
    <!-- do something with $product -->
<?php endforeach;?>

Some of this has been taken from Magento 2: get product collection using category id

  • I'm getting: Invalid template file: 'productdisplay.phtml' in module: '[Vendor]_ProductDisplay' block's name: 'productdisplay_0' - and it won't display. I'm calling it with: {{block class="Vendor\ProductDisplay\Block\Vendor_ProductDisplay" template="productdisplay.phtml"}}
    – Aravona
    Jun 14, 2017 at 14:22
  • Should be just productdisplay not Vendor_ProductDisplay in class ive updated my answer with code.
    – harri
    Jun 14, 2017 at 14:26
  • my classname is Vendor_ProductDisplay though.
    – Aravona
    Jun 14, 2017 at 14:27
  • classname should match name of the php file.
    – harri
    Jun 14, 2017 at 14:27
  • Same error still.
    – Aravona
    Jun 14, 2017 at 14:31

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.