Question

I wanted to have a product's brand name shown next to it's product name, so I created a module for this. I extended the Magento\Theme\Block\Html\Title block in order to obtain the brand name and use this in the template.

The module works as expected, but for some reason my system.log becomes filled by the following error: main.CRITICAL: Invalid template file: 'title.phtml' in module: 'Kyegil_ProductBrand' block's name: 'page.title'

What have I left out here? Why I'm I getting this error?

etc/di.xml:

<?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\Theme\Block\Html\Title" type="Kyegil\ProductBrand\Block\Html\Title" />
</config>

Block/Html/Title.php

<?php
namespace Kyegil\ProductBrand\Block\Html;

use Magento\Framework\View\Element\Template;

class Title extends \Magento\Theme\Block\Html\Title
{

protected $_coreRegistry = null;
protected $_product = null;
protected $_brand = '';


public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Framework\Registry $registry,
    array $data = []
) {
    $this->_coreRegistry = $registry;

    $this->_product = $this->_coreRegistry->registry('product');

    if(is_object($this->_product)) {
        $this->_brand = $this->_product->getData('brand');
    }

    parent::__construct($context, $data);
}


public function getBrand()
{
    if (is_array($this->_brand)) {
        return implode(", ", $this->_brand);
    }
    return strval($this->_brand);
}

}

view/frontend/templates/html/title.phtml

<?php

$cssClass = $block->getCssClass() ? ' ' . $block->getCssClass() : '';
$title = '';
if (trim($block->getPageHeading())) {
    $title = '<span class="base" data-ui-id="page-title-wrapper" ' .  $block->getAddBaseAttribute() . '>'
        . $block->escapeHtml($block->getPageHeading()) . '</span>';
}
?>
<?php if ($title): ?>
<div class="page-title-wrapper<?php /* @escapeNotVerified */ echo $cssClass; ?>">
    <?php if($block->getBrand()):?>
        <h2><span><?php echo $block->escapeHtml($block->getBrand()); ?></span></h2>
    <?php endif;?>
    <h1 class="page-title"
        <?php if ($block->getId()): ?> id="<?php /* @escapeNotVerified */ echo $block->getId();?>" <?php endif; ?>
        <?php if ($block->getAddBaseAttributeAria()): ?>
            aria-labelledby="<?php /* @escapeNotVerified */ echo $block->getAddBaseAttributeAria(); ?>"
        <?php endif; ?>>
        <?php /* @escapeNotVerified */ echo $title ?>
    </h1>
    <?php echo $block->getChildHtml(); ?>
</div>
<?php endif; ?>

UPDATE: My module doesn't have a layout xml, but even if I make one and change the template to eg 'custom.phtml', it doesn't make any difference. A new entry is still created in my system.log asking for the 'title.phtml', funnily enough every time I load a page in the admin area. This could be a clue though, since the only mentioning of 'page.title' that I can find anywhere is in the default.xml of the Magento_Backend module.

Was it helpful?

Solution 2

I solved this by overwriting the _toHtml() method of my block so that it defaults to the old template file. I reckon this is necessary to avoid conflict with other modules using \Magento\Theme\Block\Html\Title.

in Block/Html/Title.php:

protected function _toHtml()
{
    $this->setModuleName($this->extractModuleName('Magento\Theme\Block\Html\Title'));
    return parent::_toHtml();
}

Then I specified a template file in view/frontend/layout/default.xml for my own use, as Sohel Rana recommended:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="page.main.title">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Kyegil_ProductBrand::html/title.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

The module works as before, and I'm no longer having critical entries in my system.log.

OTHER TIPS

Add following line into your override class


protected $_template = 'Magento_Theme::html/title.phtml';

So your class looks like



class Title extends \Magento\Theme\Block\Html\Title
{

    protected $_coreRegistry = null;
    protected $_product = null;
    protected $_brand = '';

    protected $_template = 'Magento_Theme::html/title.phtml';

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Framework\Registry $registry,
        array $data = []
    ) {
        $this->_coreRegistry = $registry;

        $this->_product = $this->_coreRegistry->registry('product');

        if(is_object($this->_product)) {
            $this->_brand = $this->_product->getData('brand');
        }

        parent::__construct($context, $data);
    }


    public function getBrand()
    {
        if (is_array($this->_brand)) {
            return implode(", ", $this->_brand);
        }
        return strval($this->_brand);
    }

}

OR

Kyegil/ProductBrand/view/frontend/layout/default.xml


<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="page.main.title">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Magento_Theme::html/title.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top