Magento – Magento2 Add block to theme for custom phtml file

code-migrationmagento2theme

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)
        ->getProductCollection()
        ->addAttributeToSelect('*')
        ->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?

Update:

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

app/code/Vendor/ProductDisplay

I created a new class of ProductDisplay in

app/code/Vendor/ProductDisplay/ProductDisplay.php

I created a new templated in

app/code/Vendor/ProductDisplay/view/frontend/templates/productdisplay.phtml

I'm calling it in my cms page with:

{{block class="Vendor\Productdisplay\Block\ProductDisplay"  template="Vendor_ProductDisplay::productdisplay.phtml"}}

Best Answer

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:

http://inchoo.net/magento-2/how-to-create-a-basic-module-in-magento-2/

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">
    </block>
</referenceContainer>

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

<?php
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;
parent::__construct($context);
}
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