4

In a custom module I override the cart item template. It works, but my exception log is filling up with The element "checkout.cart.item.renderers" already has a child with alias "default" and alias "simple" errors.

How do I correct my code to fix this?

In my custom module I have the file app/code/MyCompany/MyModule/view/frontend/layout/checkout_cart_item_renderers.xml with the following code:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.cart.item.renderers">
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="default" template="MyCompany_MyModule::cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.default.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.default.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.default.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="simple" template="MyCompany_MyModule::cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.simple.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.simple.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.simple.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
        </referenceBlock>
    </body>
</page>

My custom template is in /app/code/MyCompany/MyModule/view/frontend/templates/cart/item/default.phtml.

I have tried removing the block first, then it doesn't load anything. Any help how to do this the right way is appreciated.

  • what do you want to do, plz specify in details. – Rakesh Jesadiya May 2 '16 at 8:43
  • I am not sure what you mean, the question is clear: overriding the template works, but it fills up my exception log, so obviously it is not the right way to do it. – tecjam May 2 '16 at 8:44
  • you can override your phtml file inside theme folder and check chagnes. – Rakesh Jesadiya May 2 '16 at 9:12
7

My version override based of method getItemRenderer of Magento\Checkout\Block\Cart\AbstractCart, used variable OverriddenTemplates.

file vendor/module/view/frontend/layout/checkout_cart_item_renderers.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<!-- override checkout cart item template -->
<referenceBlock name="checkout.cart.form">
    <action method="setOverriddenTemplates">
        <argument xsi:type="array">
            <!-- list override templates -->
            <item name="default" xsi:type="string">vendor_module::cart/item/default.phtml</item>
            <item name="simple" xsi:type="string">vendor_module::cart/item/default.phtml</item>
            <item name="virtual" xsi:type="string">vendor_module::cart/item/default.phtml</item>
        </argument>
    </action>
</referenceBlock>

Also see Complete code sample on GitHub

  • This is the correct solution, nothing else I tried worked. Also works for configurable products, which is what I needed. – Geat May 4 '18 at 15:47
1

The problem here is that the following blocks are already declared by core files of Magento 2:

  • default
  • simple

As you only want to change the template I suggest you do the following:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.cart.item.renderers">
            <referenceBlock name="default" template="MyCompany_MyModule::cart/item/default.phtml" />
            <referenceBlock name="simple" template="MyCompany_MyModule::cart/item/default.phtml" />
        </referenceBlock>
    </body>
</page>

Alternatively you can also do:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.cart.item.renderers">
            <referenceBlock name="default">
                <action method="setTemplate">
                    <argument name="template" xsi:type="string">MyCompany_MyModule::cart/item/default.phtml</argument>
                </action>
            </referenceBlock>
            <referenceBlock name="simple">
                <action method="setTemplate">
                    <argument name="template" xsi:type="string">MyCompany_MyModule::cart/item/default.phtml</argument>
                </action>
            </referenceBlock>
        </referenceBlock>
    </body>
</page>
  • I'm sorry, but neither of these methods work. They do not override the template file. – tecjam May 2 '16 at 9:49
  • @tecjam see my edited code for the right code, I missed a line -_- – Raphael at Digital Pianism May 2 '16 at 9:52
  • This still does not work for me. – tecjam May 2 '16 at 10:14
  • @tecjam try deleting both var/cache and var/generation folders and double check as it's definitely the right way to go – Raphael at Digital Pianism May 2 '16 at 10:15
  • I run: rm -rf var/* and php bin:magento cache:clean and php bin:magento cache:flush and manually delete pub/static/frontend - this makes not difference as the template is not overridden. My above code however works, apart from writing exception logs. I guess I'll just have to live with the exception logs until I find a working solution. – tecjam May 2 '16 at 10:17
0

I resolved this using Raphael's second suggestion (action setTemplate) combined with a custom Cart/Item/Renderer Block:

namespace Vendor\Module\Block;
class CartItemRenderer extends Magento\Checkout\Block\Cart\Item\Renderer
{
// I have made no customizations yet.
}

And using frontend/di.xml to replace Magento_Checkout default:

<?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\Checkout\Block\Cart\Item\Renderer" 
                type="Vendor\Module\Block\CartItemRenderer"/>
</config>

--
[Update 2016-07-08]
After looking into it some more, I realized that the setTemplate action is never used because the renderer name (eg, "simple") is really an alias, not a name, and Magento 2 requires the name in referenceBlock. The only reason the method I stated above worked is because the "simple" and "default" renderers use a relative template path (cart/item/default.phtml instead of Magento_Checkout::cart/item/default.phtml), so by changing the class block, you change the relative folder (from Magento/Checkout to Vendor/Module). This solution does not work for any of the other types ("configurable", "grouped", etc.).

TLDR; there is currently no way in layout xml to override the individual renderer templates in Magento 2. You will have to resort to theme changes, and/or do it in a Plugin intercept (helpful example here - it worked for me: https://magento.stackexchange.com/a/112485/41862).

0

Here is working code for module default.phtml file override,

Below step by step code for this functionality,

I have changed block name checkout.cart.item.renderers.override so we have to override checkout_cart_index.xml file

registration.php file,

Full path,

app/code/Package/Modulename/registration.php

code for this,

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

composer.json file,

app/code/Package/Modulename/composer.json

composer declaration,

{
    "name": "package/magento2-modulename",
    "description": "module desctiption",
    "require": {
        "php": "~5.5.0|~5.6.0"
    },
    "type": "magento2-module",
    "version": "1.4.0",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "extra": {
        "map": [
            [
                "*",
                "Package/Modulename"
            ]
        ]
    }
}

module.xml file,

Full path, app/code/Package/Modulename/etc/module.xml file

<?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="Package_Modulename" setup_version="1.0.0">
        <sequence>
                <module name="Magento_Checkout"/>
            </sequence>
        </module>
    </config>

Override checkout_cart_index.xml file from core,

app/code/Package/Modulename/view/frontend/layout/checkout_cart_index.xml 

Keep below code,

 <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <body>
                <referenceBlock class="Magento\Checkout\Block\Cart" name="checkout.cart.form" as="cart-items" template="cart/form.phtml">
                    <block class="Magento\Framework\View\Element\RendererList" name="checkout.cart.item.renderers.override" as="renderer.list.custom"/>
                </referenceBlock>
        </body>
    </page>

checkout_cart_item_renderers.xml file, file path location, app/code/Package/Modulename/view/frontend/layout/checkout_cart_item_renderers.xml

xml code for override default.phtml file

<?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="checkout.cart.item.renderers.override">
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="default" template="Package_Modulename::cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.default.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.default.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.default.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
            <block class="Magento\Checkout\Block\Cart\Item\Renderer" as="simple" template="Package_Modulename::cart/item/default.phtml">
                <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions" name="checkout.cart.item.renderers.simple.actions" as="actions">
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Edit" name="checkout.cart.item.renderers.simple.actions.edit" template="Magento_Checkout::cart/item/renderer/actions/edit.phtml"/>
                    <block class="Magento\Checkout\Block\Cart\Item\Renderer\Actions\Remove" name="checkout.cart.item.renderers.simple.actions.remove" template="Magento_Checkout::cart/item/renderer/actions/remove.phtml"/>
                </block>
            </block>
        </referenceBlock>
    </body>
</page>

template file,

app/code/Vendor/Age/view/frontend/templates/cart/item/default.phtml

Code for template,

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

/** @var $block \Magento\Checkout\Block\Cart\Item\Renderer */

$_item = $block->getItem();
$product = $_item->getProduct();
$isVisibleProduct = $product->isVisibleInSiteVisibility();
/** @var \Magento\Msrp\Helper\Data $helper */
$helper = $this->helper('Magento\Msrp\Helper\Data');
$canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinimalPriceLessMsrp($product);
?>
1111111111111111111111111111111111
<tbody class="cart item">
    <tr class="item-info">
        <td data-th="<?php echo $block->escapeHtml(__('Item')); ?>" class="col item">
            <?php if ($block->hasProductUrl()):?>
                <a href="<?php /* @escapeNotVerified */ echo $block->getProductUrl() ?>"
                   title="<?php echo $block->escapeHtml($block->getProductName()) ?>"
                   tabindex="-1"
                   class="product-item-photo">
            <?php else:?>
                <span class="product-item-photo">
            <?php endif;?>
            <?php echo $block->getImage($block->getProductForThumbnail(), 'cart_page_product_thumbnail')->toHtml(); ?>
            <?php if ($block->hasProductUrl()):?>
                </a>
            <?php else: ?>
                </span>
            <?php endif; ?>
            <div class="product-item-details">
                <strong class="product-item-name">
                    <?php if ($block->hasProductUrl()):?>
                        <a href="<?php /* @escapeNotVerified */ echo $block->getProductUrl() ?>"><?php echo $block->escapeHtml($block->getProductName()) ?></a>
                    <?php else: ?>
                        <?php echo $block->escapeHtml($block->getProductName()) ?>
                    <?php endif; ?>
                </strong>
                <?php if ($_options = $block->getOptionList()):?>
                    <dl class="item-options">
                        <?php foreach ($_options as $_option) : ?>
                            <?php $_formatedOptionValue = $block->getFormatedOptionValue($_option) ?>
                            <dt><?php echo $block->escapeHtml($_option['label']) ?></dt>
                            <dd>
                                <?php if (isset($_formatedOptionValue['full_view'])): ?>
                                    <?php /* @escapeNotVerified */ echo $_formatedOptionValue['full_view'] ?>
                                <?php else: ?>
                                    <?php /* @escapeNotVerified */ echo $_formatedOptionValue['value'] ?>
                                <?php endif; ?>
                            </dd>
                        <?php endforeach; ?>
                    </dl>
                <?php endif;?>
                <?php if ($messages = $block->getMessages()): ?>
                    <?php foreach ($messages as $message): ?>
                        <div class="cart item message <?php /* @escapeNotVerified */ echo $message['type'] ?>"><div><?php echo $block->escapeHtml($message['text']) ?></div></div>
                    <?php endforeach; ?>
                <?php endif; ?>
                <?php $addInfoBlock = $block->getProductAdditionalInformationBlock(); ?>
                <?php if ($addInfoBlock): ?>
                    <?php echo $addInfoBlock->setItem($_item)->toHtml() ?>
                <?php endif;?>
            </div>
        </td>

        <?php if ($canApplyMsrp): ?>
            <td class="col msrp" data-th="<?php echo $block->escapeHtml(__('Price')); ?>">
                <span class="pricing msrp">
                    <span class="msrp notice"><?php /* @escapeNotVerified */ echo __('See price before order confirmation.'); ?></span>
                    <?php $helpLinkId = 'cart-msrp-help-' . $_item->getId(); ?>
                    <a href="#" class="action help map" id="<?php /* @escapeNotVerified */ echo($helpLinkId); ?>" data-mage-init='{"addToCart":{"helpLinkId": "#<?php /* @escapeNotVerified */ echo $helpLinkId;?>","productName": "<?php /* @escapeNotVerified */ echo $product->getName(); ?>","showAddToCart": false}}'>
                        <span><?php /* @escapeNotVerified */ echo __("What's this?"); ?></span>
                    </a>
                </span>
            </td>
        <?php else: ?>
            <td class="col price" data-th="<?php echo $block->escapeHtml(__('Price')); ?>">
                <?php echo $block->getUnitPriceHtml($_item); ?>
            </td>
        <?php endif; ?>
        <td class="col qty" data-th="<?php echo $block->escapeHtml(__('Qty')); ?>">
            <div class="field qty">
                <label class="label" for="cart-<?php /* @escapeNotVerified */ echo $_item->getId() ?>-qty">
                    <span><?php /* @escapeNotVerified */ echo __('Qty') ?></span>
                </label>
                <div class="control qty">
                    <input id="cart-<?php /* @escapeNotVerified */ echo $_item->getId() ?>-qty"
                           name="cart[<?php /* @escapeNotVerified */ echo $_item->getId() ?>][qty]"
                           data-cart-item-id="<?php /* @escapeNotVerified */ echo $_item->getSku() ?>"
                           value="<?php /* @escapeNotVerified */ echo $block->getQty() ?>"
                           type="number"
                           size="4"
                           title="<?php echo $block->escapeHtml(__('Qty')); ?>"
                           class="input-text qty"
                           maxlength="12"
                           data-validate="{required:true,'validate-greater-than-zero':true}"
                           data-role="cart-item-qty"/>
                </div>
            </div>
        </td>

        <td class="col subtotal" data-th="<?php echo $block->escapeHtml(__('Subtotal'));?>">
            <?php if ($canApplyMsrp): ?>
                <span class="cart msrp subtotal">--</span>
            <?php else: ?>
                <?php echo $block->getRowTotalHtml($_item); ?>
            <?php endif; ?>
        </td>
    </tr>
    <tr class="item-actions">
        <td colspan="100">
            <div class="actions-toolbar">
                <?php /* @escapeNotVerified */ echo $block->getActions($_item) ?>
            </div>
        </td>
    </tr>
</tbody>

Now you have to just override core block

function _getRendererList()

from Magento\Checkout\Block\Cart\AbstractCart.php file.

code for function,

protected function _getRendererList()
    {
        echo 'tets';exit;
        return $this->getRendererListName() ? $this->getLayout()->getBlock(
            $this->getRendererListName()
        ) : $this->getChildBlock(
            'renderer.list.custom'
        );
    }

Check above code in your case.

plz after apply above code just run command,

php bin/magento setup:static-content:deploy

remove var folder and browser cache.

This is working code and you can check after var/exception.log no any error or notice generate.

Plz let me know if any issue occours.

  • Hi @Rakesh, while I appreaciate the answer and the above code works (my module does it the exact same way!!) please have a look into your var/exception.log file and you will see the exception error this question is all about. – tecjam May 2 '16 at 9:40
  • I have update my answer. plz refer again and check your exception.log file. – Rakesh Jesadiya May 3 '16 at 5:49
  • Hi, your above code works, but I'm overriding only checkout_onepage_success.xml file in my custom theme and still I'm getting the exception that is mentioned in the question. Do you have any idea regarding this? – anujeet Feb 17 '17 at 12:54

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.