0

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"}}
Aravona
  • 367
  • 6
  • 21
  • 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 '17 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 '17 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 '17 at 12:49
  • Ok, but where do I create the block? – Aravona Jun 14 '17 at 12:49
  • Vendor\Module\Block\CustomProducts.php – harri Jun 14 '17 at 12:50
  • In my theme? or as a new extension, which was my question – Aravona Jun 14 '17 at 12:50
  • Yes in an extension sorry i call it a module above but you can't create like this in a theme other than calling object manager that you said you wanted to avoid. – harri Jun 14 '17 at 12:51
  • Maybe its the second cap in module name? ProductDisplay change to Productdisplay – harri Jun 14 '17 at 15:04
  • No I've used that before in m1 and m2 without an issue. – Aravona Jun 14 '17 at 15:05
  • But i mean that they dont match? Block Vendor_ProductDisplay not Vendor_Productdisplay – harri Jun 14 '17 at 15:09
  • sorry that was just a typo, I didn't copy paste. – Aravona Jun 14 '17 at 15:10
  • Are you running the setup:upgrade command? – harri Jun 14 '17 at 15:13
  • Yup, and cleared the cache, run static content deploy. – Aravona Jun 14 '17 at 15:14
  • hmm im not sure what's quite going wrong, we can maybe try the layout option of adding the block added into my answer. Maybe just try having hello world in template file for now while we debug. – harri Jun 14 '17 at 17:24
  • Also you can actually basically do this with a widget within CMS. – harri Jun 14 '17 at 17:53

1 Answers1

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:

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

harri
  • 5,465
  • 6
  • 44
  • 100
  • 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 '17 at 14:22
  • Should be just productdisplay not Vendor_ProductDisplay in class ive updated my answer with code. – harri Jun 14 '17 at 14:26
  • my classname is Vendor_ProductDisplay though. – Aravona Jun 14 '17 at 14:27
  • classname should match name of the php file. – harri Jun 14 '17 at 14:27
  • Same error still. – Aravona Jun 14 '17 at 14:31
  • Where is your template file stored? have you updated the code to match mine above notice i changed template= – harri Jun 14 '17 at 14:32
  • the template is in view/frontend/templates and yes. – Aravona Jun 14 '17 at 14:32
  • Could you update your question a bit with these details and where you are at so far so i can have a look over – harri Jun 14 '17 at 14:39
  • I have updated how i think it should be not sure of the collection code however may need to take a look at this however maybe start with helloworld in template and we will call this into page with block – harri Jun 14 '17 at 14:49
  • I've updated my question. – Aravona Jun 14 '17 at 15:02