0

I have a number of products that share a lot of the same content. It is becoming increasingly difficult to keep all of the product pages updated when new products are released or changed.

I would like to take the common content elements and place them into a content block and place the block onto each product. The problem with this is that some of the shared content needs to be slightly different for each product. Basically, the comparison table needs to highlight the product the the user is currently viewing.

The only way I can see to do this is to place the block into a module and create a block with an argument for the selected product. I was hoping to avoid having to do that because it seems like a lot of work to achieve so little.

1 Answer 1

2

I think you have a number of options to consider. What follows is an exploration of the different options. These examples use the cms homepage, but can be used anywhere.

I think your best bet may be to design a block that's reusable by passing values to it in layout xml via a block method, something like the third example.

/app/code/Wabbit42/TemplateValue/view/frontend/layout/cms_index_index.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>
        <referenceContainer name="content">
            <!-- First is the normal block -->
            <block class="Wabbit42\TemplateValue\Block\Original\Home" name="extra_homepage_block_one" template="Wabbit42_TemplateValue::home.phtml" before="-"/>

            <!-- Second is a manual change of the text in the constructor of a block extending the first-->
            <block class="Wabbit42\TemplateValue\Block\Extend\Home" name="extra_homepage_block_two" template="Wabbit42_TemplateValue::home.phtml" after="extra_homepage_block_one"/>

            <!-- Third is doing the same but in layout XML so no new block class required -->
            <block class="Wabbit42\TemplateValue\Block\Original\Home" name="extra_homepage_block_three" template="Wabbit42_TemplateValue::home.phtml" after="extra_homepage_block_two">
                <action method="setData">
                    <argument name="key" translate="false" xsi:type="string">getText</argument>
                    <argument name="value" translate="true" xsi:type="string">third</argument>
                </action>
            </block>

            <!-- Fourth is using just a template block with no class -->
            <block name="extra_homepage_block_four" template="Wabbit42_TemplateValue::home.phtml" after="extra_homepage_block_three">
                <arguments>
                    <argument name="layout_text" translate="true" xsi:type="string">fourth</argument>
                </arguments>
            </block>

            <!-- Fifth is using the view model and passing values -->
            <block name="extra_homepage_block_five" template="Wabbit42_TemplateValue::home.phtml" after="extra_homepage_block_four">
                <arguments>
                    <argument name="view_model" xsi:type="object">Wabbit42\TemplateValue\ViewModel\Home</argument>
                </arguments>
            </block>

        </referenceContainer>
    </body>
</page>

/app/code/Wabbit42/TemplateValue/view/frontend/templates/home.phtml:

<?php
$viewModel = $block->getViewModel();
$viewModel ? $text = $viewModel->getText() : $text = null;

switch ($block->getText()) {
    case 'first':
        $explanationText = 'Value from Block getText() method in \Wabbit42\TemplateValue\Block\Original\Home';
        break;
    case 'second':
        $explanationText = 'Value from Block constructor in \Wabbit42\TemplateValue\Block\Extend\Home';
        break;
    case 'third':
        $explanationText = 'Value from XML injected value in cms_index_index.xml';
        break;
    }
?>

<div>
    <?php if ($block->getText()): ?>
        <p><strong><?=$block->getText()?></strong> -> <?=$explanationText?> | Block Class = <?=get_class($block)?></p>
    <?php endif; ?>

    <?php if ($block->getLayoutText()): ?>
        <p><strong><?=$block->getLayoutText()?></strong> -> Value from XML of classless block & injected value in cms_index_index.xml | Block Class = <?=get_class($block)?></p>
    <?php endif; ?>

    <?php if ($text): ?>
        <p><strong><?=$text?></strong> -> Value from ViewModel getText() method in \Wabbit42\TemplateValue\ViewModel\Home | Block Class = <?=get_class($block)?></p>
    <?php endif; ?>
</div>

/app/code/Wabbit42/TemplateValue/Block/Original/Home.php:

<?php
namespace Wabbit42\TemplateValue\Block\Original;

use Magento\Framework\View\Element\Template\Context;

class Home extends \Magento\Framework\View\Element\Template
{
    /**
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param array $data
     */
    public function __construct(
        Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    /**
     * Returns the text value in $this->_data['getText']
     *
     * @return string
     */
    public function getText()
    {
        if (!$this->getData('getText')) {
            $this->setData('getText', 'first');
        }
        return $this->getData('getText');
    }
}

/app/code/Wabbit42/TemplateValue/Block/Extend/Home.php:

<?php
namespace Wabbit42\TemplateValue\Block\Extend;

use Magento\Framework\View\Element\Template\Context;

class Home extends \Wabbit42\TemplateValue\Block\Original\Home
{
    /**
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param array $data
     */
    public function __construct(
        Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->setData('getText', 'second');
    }
}

/app/code/Wabbit42/TemplateValue/ViewModel/Home.php:

<?php
namespace Wabbit42\TemplateValue\ViewModel;

class Home implements \Magento\Framework\View\Element\Block\ArgumentInterface
{

    public function getText()
    {
        return 'fifth';
    }
}

/app/code/Wabbit42/TemplateValue/etc/module.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Wabbit42_TemplateValue" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Cms"/>
        </sequence>
    </module>
</config>

/app/code/Wabbit42/TemplateValue/registration.php:

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Wabbit42_TemplateValue',
    __DIR__
);

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.