3

I have a custom attribute for products set in the admin that I'd like to render on the new Order transactional email; I've tried in different ways but I am not able to make it works.

this is my code:

Vendor/Email/Block/Order/Email/Items/DefaultItems.php

 <?php /** * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace <Vendor>\Email\Block\Order\Email\Items; use Magento\Sales\Model\Order\Creditmemo\Item as CreditmemoItem; use Magento\Sales\Model\Order\Invoice\Item as InvoiceItem; use Magento\Sales\Model\Order\Item as OrderItem; use Magento\Catalog\Model\ProductFactory; /** * Sales Order Email items default renderer * * @author Magento Core Team <[email protected]> */ class DefaultItems extends \Magento\Framework\View\Element\Template { public $productFactory; /** * Constructor * * @param Template\Context $context * @param array $data */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, ProductFactory $productFactory, array $data = [] ) { $this->productFactory = $productFactory; parent::__construct($context, $data); } /** * Retrieve current order model instance * * @return \Magento\Sales\Model\Order */ public function getOrder() { return $this->getItem()->getOrder(); } /** * @return array */ public function getItemOptions() { $result = []; if ($options = $this->getItem()->getOrderItem()->getProductOptions()) { if (isset($options['options'])) { $result = array_merge($result, $options['options']); } if (isset($options['additional_options'])) { $result = array_merge($result, $options['additional_options']); } if (isset($options['attributes_info'])) { $result = array_merge($result, $options['attributes_info']); } } return $result; } /** * @param string|array $value * @return string */ public function getValueHtml($value) { if (is_array($value)) { return sprintf( '%d', $value['qty'] ) . ' x ' . $this->escapeHtml( $value['title'] ) . " " . $this->getItem()->getOrder()->formatPrice( $value['price'] ); } else { return $this->escapeHtml($value); } } /** * @param mixed $item * @return mixed */ public function getSku($item) { if ($item->getOrderItem()->getProductOptionByCode('simple_sku')) { return $item->getOrderItem()->getProductOptionByCode('simple_sku'); } else { return $item->getSku(); } } /** * Return product additional information block * * @return \Magento\Framework\View\Element\AbstractBlock */ public function getProductAdditionalInformationBlock() { return $this->getLayout()->getBlock('additional.product.info'); } /** * Get the html for item price * * @param OrderItem|InvoiceItem|CreditmemoItem $item * @return string */ public function getItemPrice($item) { $block = $this->getLayout()->getBlock('item_price'); $block->setItem($item); return $block->toHtml(); } public function getImage($id) { $product = $this->productFactory->create()->load($id); return $this->getBaseUrl() . 'media/catalog/product' . $product->getImage(); } public function getAttr($id) { $product = $this->productFactory->create()->load($id)->getAttributes(); return $product; } } 

And this is the code for the template file:

Vendor/Email/view/frontend/templates/email/items/order/default.phtml

<?php /** * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ // @codingStandardsIgnoreFile /** @var $block \Magento\Sales\Block\Order\Email\Items\DefaultItems */ /** @var $_item \Magento\Sales\Model\Order\Item */ $_item = $block->getItem(); $_order = $_item->getOrder(); ?> <tr> <td class="item-info<?php if ($block->getItemOptions()): ?> has-extra<?php endif; ?>"> <img src="<?php echo $block->getImage($_item->getProductId()); ?>" alt="<?php echo $block->escapeHtml($_item->getName()); ?>" class="product-image" width="149" height="109" /> <div class="product-info"> <p class="product-name"><strong><?= $block->escapeHtml($_item->getName()) ?></strong></p> <p><?php echo $block->getAttr(); ?></p> <?php if ($block->getItemOptions()): ?> <dl class="item-options"> <?php foreach ($block->getItemOptions() as $option): ?> <dt class="<?= /* @escapeNotVerified */ $option['label'] ?>"><?= /* @escapeNotVerified */ $option['label'] ?>: <span class="<?= /* @escapeNotVerified */ $option['label'] ?>"> <?= /* @escapeNotVerified */ nl2br($option['value']) ?> </span> </dt> <?php endforeach; ?> </dl> <?php endif; ?> <?php $addInfoBlock = $block->getProductAdditionalInformationBlock(); ?> <?php if ($addInfoBlock) :?> <?= $addInfoBlock->setItem($_item)->toHtml() ?> <?php endif; ?> <?= $block->escapeHtml($_item->getDescription()) ?> </div> </td> <td class="item-qty"><?= /* @escapeNotVerified */ $_item->getQtyOrdered() * 1 ?></td> <td class="item-price"> <?= /* @escapeNotVerified */ $block->getItemPrice($_item); ?> </td> </tr> <?php if ($_item->getGiftMessageId() && $_giftMessage = $this->helper('Magento\GiftMessage\Helper\Message')->getGiftMessage($_item->getGiftMessageId())): ?> <tr> <td colspan="3" class="item-extra"> <table class="message-gift"> <tr> <td> <h3><?= /* @escapeNotVerified */ __('Gift Message') ?></h3> <strong><?= /* @escapeNotVerified */ __('From:'); ?></strong> <?= $block->escapeHtml($_giftMessage->getSender()) ?> <br /><strong><?= /* @escapeNotVerified */ __('To:'); ?></strong> <?= $block->escapeHtml($_giftMessage->getRecipient()) ?> <br /><strong><?= /* @escapeNotVerified */ __('Message:'); ?></strong> <br /><?= $block->escapeHtml($_giftMessage->getMessage()) ?> </td> </tr> </table> </td> </tr> <?php endif; ?> 

So my method is getAttr() but it always return NULL, I was trying to echo all the attributes and then target the ones I am interested in, but I can't get it to work at the moment. i was able the get the product image with the getImage() method

2 Answers 2

1

I will answer my own question in case someone else will stumble upon it,

This is what I ultimately did (I changed the method name to a more accurate one):

Like @kusum suggested

In <Vendor>/Email/Block/Order/Email/Items/DefaultItems.php I put

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

and in <Vendor>/Email/view/frontend/templates/email/items/order/default.phtml I've called the method like so:

$_product = $block->getProductModel($_item->getProductId()); <?php echo $_product->getAttributeText("lead_time_title"); ?> 

but what ultimately did the trick was to copy the exact same method over to

<Vendor>/Email/Block/Order/Email/Items/Order/DefaultOrder.php

Otherwise getProductModel it would always return null

3
  • Hi, How to override defaultorder.php file. Commented Aug 17, 2019 at 10:10
  • Can you share you updated code? Commented Aug 17, 2019 at 10:10
  • I'm doing this same work Commented Aug 17, 2019 at 10:11
0

You need to change your way to get product attributes in phtml: you can get attributes using <?php $attributes = $block->getAttr($_item->getProductId()); ?> and after that you need to change function defined in block as:

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

Now you can get all attributes in below way:

echo $attributes->getName(); echo $attributes->getPrice(); 

In this way you can get any other custom attribute's value.

Hope this was helpful.

1
  • Hello, sorry for the late reply; I've tried that but php return this error: PHP Fatal error: Uncaught Error: Call to a member function getAttr() on null And I don't understand why it's returning null, because I use the same function for getImage() and it works Commented Jul 6, 2017 at 16:40

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.