2

I am attempting to override the __construct method in the Magento\Catalog\block\Product\View block so that I can access the Magento\Eav\Model\Entity\Attribute\SetFactory to get the AttributeSetName of a product in the addtocart.phtml. However, I keep running into a 404 Error.

I created a module and extended the Magento\Catalog\Block\Product\View class.

namespace MyVendor\MyModule\Block\Product;

use Magento\Catalog\Block\Product\View as BaseView;

class View extends BaseView {

    protected $_attributeSetFactory;

    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\Url\EncoderInterface $urlEncoder,
        \Magento\Framework\Json\EncoderInterface $jsonEncoder,
        \Magento\Framework\Stdlib\StringUtils $string,
        \Magento\Catalog\Helper\Product $productHelper,
        \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
        \Magento\Framework\Locale\FormatInterface $localeFormat,
        \Magento\Customer\Model\Session $customerSession,
        ProductRepositoryInterface $productRepository,
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
        \Magento\Eav\Model\Entity\Attribute\SetFactory $attributeSetFactory,
        array $data = []
    ) {
        $this->_attributeSetFactory = $attributeSetFactory;
        parent::__construct(
            $context,
            $urlEncoder,
            $jsonEncoder,
            $string,
            $productHelper,
            $productTypeConfig,
            $localeFormat,
            $customerSession,
            $productRepository,
            $priceCurrency,
            $data
        );
    }

/**
 * Add meta information from product to head block
 *
 * @return \Magento\Catalog\Block\Product\View
 */
protected function _prepareLayout()
{
    parent::_prepareLayout();
}

}

In the Magento\view\frontend\templates\product\view\addtocart.phtml template I wasn't sure if I had to change the line /** @var $block \Magento\Catalog\Block\Product\View */ to reference my block instead of the core block either.

Snippet from MyVendor\MyModule\view\frontend\templates\product\view\addtocart.phtml:

...
/** @var $block \Magento\Catalog\Block\Product\View */
?>
<?php $_product = $block->getProduct(); ?>
<?php echo $block->getAttributeSetName(); ?>
<?php $buttonTitle = __('Add to Cart'); ?>
...

After reading documentation I do not think I am injecting the factory correctly in the construct because before getting the 404 error I was having issues with the order the parameters are passed in the __construct. However, after I cleared the cache I get the 404 error. Any help and direction would greatly be appreciated.

This is my di.xml file:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Block\Product\View" type="MyVendor\MyModule\Block\Product\View" />
</config>

2 Answers 2

3

So after taking everyones suggestions and getting as far as being able to render the product detail page without any errors but the block addtocart.phtml would not appear at all. I ran into this stackoverflow question Overriding Block in Magento 2 and I realized that the accepted answer allowed for my block to be rendered on the page.

Even though my block was overwritten, the template name is determined by module name of a block and the template attribute of the block and therefore needed to add the following method to my block:

protected function _toHtml()
    {
        $this->setModuleName($this->extractModuleName('Magento\Catalog\Block\Product\View'));
        return parent::_toHtml();
    }

To be able to render the template. Still not completely clear on the reason why I need to do this, will have to do more research, but this allowed the block to be overwritten and display the appropriate custom template.

thanks all for the help :)

2
  • Thank you! I searched for 2 hours why there is no output if I override Magento\Catalog\Block\Product\View with my own block. After adding this _toHtml() method it finally works... only god knows why.
    – Alex
    Feb 15, 2017 at 16:55
  • Thanks really helpful, could have spent days trying to figure that out
    – Alex
    May 31, 2017 at 12:55
1

The order of the constructor parameters must match the order of the original constructor. Extra parameters should come last, before the $data parameter.

So your method should look like this:

public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Framework\Url\EncoderInterface $urlEncoder,
        \Magento\Framework\Json\EncoderInterface $jsonEncoder,
        \Magento\Framework\Stdlib\StringUtils $string,
        \Magento\Catalog\Helper\Product $productHelper,
        \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig,
        \Magento\Framework\Locale\FormatInterface $localeFormat,
        \Magento\Customer\Model\Session $customerSession,
        ProductRepositoryInterface $productRepository,
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
        \Magento\Eav\Model\Entity\Attribute\SetFactory $attributeSetFactory,
        array $data = []
    ) {
        $this->_attributeSetFactory = $attributeSetFactory;
        parent::__construct(
            $context,
            $urlEncoder,
            $jsonEncoder,
            $string,
            $productHelper,
            $productTypeConfig,
            $localeFormat,
            $customerSession,
            $productRepository,
            $priceCurrency,
            $data
        );
    }
7
  • Order of the parameters in the constructor is not important. only the parameters that have default values should go last. And only when calling the parent constructor you have to use the same order as declared in the parent class.
    – Marius
    Jul 5, 2016 at 21:03
  • @Marius I always thought it was important Jul 5, 2016 at 21:15
  • Hi @RaphaelatDigitalPianism I rearranged the order of the constructor parameters, I even added a prepareLayout() method (not sure if this is needed) and I am getting this error Fatal error: Uncaught TypeError: Argument 11 passed to MyVendor\MyModule\Block\Product\View::__construct() must be an instance of Magento\Eav\Model\Entity\Attribute\SetFactory, array given, called in .../var/generation/MyVendor/MyModule/Block/Produc‌t/View/Interceptor.php on line 15 and defined in .../app/code/MyVendor/MyModule/Block/Product/View.php Jul 5, 2016 at 21:36
  • @NoemiQuezada try deleting var/generation. Also could you post your di.xml file pls? Jul 5, 2016 at 21:46
  • @RaphaelatDigitalPianism I deleted the var/generation, I posted the di.xml as an edit to the question. Deleting the var/generation loaded my page, but the addtocart block which assesses the block I extended does not get loaded. hmm... Jul 5, 2016 at 22:14

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.