0

I'm trying to add a custom product attribute 'renewal' to the order confirmation email. I have several configurable products and they are returning the parent product attribute value rather than the correct child product.

The 'renewal' product attribute is a text field that may contain some html markup. It will normally be different for the parent product and the child product when the product is a configurable product. Site is running Magento 2.4.6

Here is the line of code I'm using in /Vendor/Theme/Magento_Sales/templates/email/items/order/default.phtml

<?= $_item->getProduct()->getData('renewal'); ?>

I also attempted to extend DefaultItems, but it does not appear to be working properly (/Vendor/Module/)

public function getRenewal($id){
    $product = $this->productFactory->create()->load($id);
    return $product->getRenewal();
}

Then calling the function in the default.phtml template

<?= $_item->getRenewal($_item) ?>

This is the complete /Vendor/Theme/Magento_Sales/templates/email/items/order/default.phtml file (I had attempted to integrate this into the module, but it did not load correctly).

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

// phpcs:disable Magento2.Templates.ThisInTemplate
// phpcs:disable Magento2.Files.LineLength, Generic.Files.LineLength

/** @var $block \Magento\Sales\Block\Order\Email\Items\DefaultItems */

/** @var $_item \Magento\Sales\Model\Order\Item */
/** @var \Magento\Framework\Escaper $escaper */
$_item = $block->getItem();
$_order = $_item->getOrder();
?>
<tr>
    <td class="item-info<?= ($block->getItemOptions() ? ' has-extra' : '') ?>">
        <p class="product-name"><?= $escaper->escapeHtml($_item->getName()) ?></p>
        <p class="sku"><?= $escaper->escapeHtml(__('SKU')) ?>: <?= $escaper->escapeHtml($block->getSku($_item)) ?></p>
        <?php if ($block->getItemOptions()): ?>
            <dl class="item-options">
            <?php foreach ($block->getItemOptions() as $option): ?>
                <dt><strong><em><?= $escaper->escapeHtml($option['label']) ?></em></strong></dt>
                <dd>
                    <?= /* @noEscape */  nl2br($option['value']) ?>
                </dd>
            <?php endforeach; ?>
            </dl>
        <?php endif; ?>
        <?php $addInfoBlock = $block->getProductAdditionalInformationBlock(); ?>
        <?php if ($addInfoBlock):?>
            <?= $addInfoBlock->setItem($_item)->toHtml() ?>
        <?php endif; ?>
        <p><?= $_item->getProduct()->getData('renewal'); ?></p>
        
        <?= $escaper->escapeHtml($_item->getDescription()) ?>
    </td>
    <td class="item-qty"><?= (float) $_item->getQtyOrdered() ?></td>
    <td class="item-price">
       <?= $block->getOriginalPrice($_item) ?><br>
       <?= $block->getDiscountAmount($_item) ?><br>       
        <?= /* @noEscape */ $block->getItemPrice($_item) ?>
    </td>
</tr>
<?php if ($_item->getGiftMessageId()
    && $_giftMessage = $this->helper(\Magento\GiftMessage\Helper\Message::class)
        ->getGiftMessage($_item->getGiftMessageId())
): ?>
    <tr>
    <td colspan="3" class="item-extra">
        <table class="message-gift">
            <tr>
                <td>
                    <h3><?= $escaper->escapeHtml(__('Gift Message')) ?></h3>
                    <strong><?= $escaper->escapeHtml(__('From:')) ?></strong> <?= $escaper->escapeHtml($_giftMessage->getSender()) ?>
                    <br /><strong><?= $escaper->escapeHtml(__('To:')) ?></strong> <?= $escaper->escapeHtml($_giftMessage->getRecipient()) ?>
                    <br /><strong><?= $escaper->escapeHtml(__('Message:')) ?></strong>
                    <br /><?= $escaper->escapeHtml($_giftMessage->getMessage()) ?>
                </td>
            </tr>
        </table>
    </td>
</tr>
<?php endif; ?>

I created a custom module to extend the DefaultItems class (I have replaced my custom vendor and module names with Vendor and Module respectively). This does not appear to be working currently.

registration.php

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

etc/module.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <module name="Vendor_Module" setup_version="1.0.0" />
    </config>

etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Sales\Block\Order\Email\Items\DefaultItems" type="Vendor\Module\Block\Order\Email\Items\DefaultItems"/>
</config>

Block/Order/Email/Items/DefaultItems.php

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

namespace Vendor\Module\Block\Order\Email\Items;

use Magento\Catalog\Model\ProductFactory;

class DefaultItems extends \Magento\Sales\Block\Order\Email\Items\DefaultItems
{
    public function getProductModel($id)
    {
        $product = $this->productFactory->create()->load($id);
        return $product;
    }
    
    public function getRenewal($id){
           $product = $this->productFactory->create()->load($id);
            return $product->getRenewal();
    }

1 Answer 1

0

I was able to get this figured out thanks to this post on the Magento forums; Get Child Product Name Shipment Email

I added this code in which checks the current $_item for children (getHasChildren()) and outputs the child attribute, otherwise it outputs the normal product attribute.

I abandoned the module as it became unnecessary.

    <?php if ($_item->getHasChildren()){
        foreach($_item->getChildrenItems() as $item){
            $product = $item->getProduct();
            $productRenewal = $product->getRenewal();
            echo "<p>".$productDiscount."</p>"."<p>".$productRenewal."</p>";
        };
    } else {
        echo "<p>".$_item->getProduct()->getRenewal()."</p>";            
    }; ?>

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.