Magento 2.3 - Product images in order history
-
14-04-2021 - |
Domanda
I want to load max 3 product images in the order history page on customer account.
I currently have a perfectly working code using $objectManager
. But because Magento does not recommend to use objectManager, I want to transform this into a module.
How can I transform this code into a module?
Code:
<?php $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$_product = $objectManager->get('Magento\Catalog\Model\Product')->load($itm->getProductId());
$imageHelper = $objectManager->get('\Magento\Catalog\Helper\Image');
$image_url = $imageHelper->init($_product, 'product_page_image_small')->setImageFile($_product->getImage())->resize(160, 160)->getUrl();?>
EDIT:
namespace Vendor\OrderProductImage\Block\Item;
class Renderer extends \Magento\Framework\View\Element\Template
{
public function getProductCollectionWithImage(array $productIds)
{
$filter = $this->filterBuilder->setField('entity_id')
->setConditionType('in')
->setValue($productIds)
->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilters([$filter])
->create();
$result = $this->productRepository->getList($searchCriteria);
$parsedCollection = $this->collectionFactory->create();
if ($result->getTotalCount() > 0) {
foreach ($result->getItems() as $item) {
$item->setImage($this->buildImage($item));
$parsedCollection->addItem($item);
}
}
return $parsedCollection;
}
private function buildImage(\Magento\Catalog\Api\Data\ProductInterface $item)
{
return $this->imageBuilder->create($item, 'category_page_grid')->toHtml();
}
}
History.phtml
<?php foreach ($_orders as $_order) : ?>
<div class="order-row row align-items-center" onclick="window.location = '<?= $block->escapeUrl($block->getViewUrl($_order)) ?>'">
<div class="order-row-properties col-sm-3">
<a href="<?= $block->escapeUrl($block->getViewUrl($_order)) ?>">
<strong class="order-row-date"><?= $block->escapeHtml($_order->getRealOrderId()) ?> - <?= $block->formatDate($_order->getCreatedAt(), \IntlDateFormatter::LONG) ?></strong>
</a>
<p class="order-row-status"><?= $block->escapeHtml($_order->getStatusLabel()) ?></p>
</div>
<div class="order-row-list col-sm-8">
<ul class="">
<?php $items = $_order->getAllVisibleItems(); $item = array_slice($items, 0, 3); foreach($item as $itm): ?>
<?php $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$_product = $objectManager->get('Magento\Catalog\Model\Product')->load($itm->getProductId());
$imageHelper = $objectManager->get('\Magento\Catalog\Helper\Image');
$image_url = $imageHelper->init($_product, 'product_page_image_small')->setImageFile($_product->getImage())->resize(160, 160)->getUrl();?>
<li class="order-row-item">
<div class="order-row-product">
<div class="order-row-product-image">
<img src="<?php echo $image_url;?>" border="0" alt="order-product-image" />
</div>
<div class="order-row-product-name">
<?php echo substr($this->escapeHtml($itm->getName()), 0, 20) ?>
</div>
</div>
</li>
<?php endforeach;?>
</ul>
</div>
<div class="order-row-icon col-sm-1">
<i class="fal fa-chevron-right"></i>
</div>
</div>
<?php endforeach; ?>
Soluzione
I have written a simple module that creates a block like yours: it is available at https://bitbucket.org/magstaging/productlistwithimage/src/master/. In the template, you will see the image is rendered.
There were 2 issues with the template you showed:
- using the object manager is bad practice and you seem to know about it and willing to improve your code
- also, your template was loading the product for each product in your listing and that has big impact on speed with your site
I have updated the module and the syntax below can work.
<?php
/** @var \Mbs\ProductListWithImage\Block\OrderHistoryItems $blockItems */
$blockItems = $block->getLayout()->createBlock(\Mbs\ProductListWithImage\Block\OrderHistoryItems::class)
->setTemplate('Mbs_ProductListWithImage::list.phtml');
echo $blockItems->toHtml();
Looking at your template, you should use the following:
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// phpcs:disable Magento2.Templates.ThisInTemplate
/** @var \Magento\Sales\Block\Order\History $block */
/** @var \Mbs\ProductListWithImage\ViewModel\OrderHistoryItems $viewModel */
$viewModel = $block->getData('viewModel');
?>
<?php $_orders = $block->getOrders(); ?>
<?= $block->getChildHtml('info') ?>
<?php if ($_orders && count($_orders)) : ?>
<?php foreach ($_orders as $_order) : ?>
<div class="order-row row align-items-center" onclick="window.location = '<?= $block->escapeUrl($block->getViewUrl($_order)) ?>'">
<div class="order-row-properties col-sm-3">
<a href="<?= $block->escapeUrl($block->getViewUrl($_order)) ?>">
<strong class="order-row-date"><?= $block->escapeHtml($_order->getRealOrderId()) ?> - <?= $block->formatDate($_order->getCreatedAt(), \IntlDateFormatter::LONG) ?></strong>
</a>
<p class="order-row-status"><?= $block->escapeHtml($_order->getStatusLabel()) ?></p>
</div>
<div class="order-row-list col-sm-8">
<ul class="">
<?php
$items = $viewModel->getOrderItems($_order, 3);
foreach($items as $item): ?>
<li class="order-row-item">
<div class="order-row-product">
<div class="order-row-product-image">
<?= $viewModel->getImageHtml($item);?>
</div>
<div class="order-row-product-name">
<?= substr($block->escapeHtml($item->getName()), 0, 20) ?>
</div>
</div>
</li>
<?php endforeach;?>
</ul>
</div>
<div class="order-row-icon col-sm-1">
<i class="fal fa-chevron-right"></i>
</div>
</div>
<?php endforeach;?>
<?php else : ?>
<div class="message info empty"><span><?= $block->escapeHtml(__('You have placed no orders.')) ?></span></div>
<?php endif ?>
Altri suggerimenti
**Try to do this following way.**
create a file in this location.
app/code/TechSolve/ImageInOrderHistory/etc/di.xml
<?xml version="1.0" ?>
<!--
/**
* TechSolve_ImageInOrderHistory
*
* PHP version 7.x
*
* @category PHP
* @package TechSolve\ImageInOrderHistory
* @author TechSolve Team
* @copyright 2020 Copyright (c) TechSolve
**/
-->
<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\History" type="TechSolve\ImageInOrderHistory\Block\Order\History" />
</config>
==> Next step. create a file in this location.
app/code/TechSolve/ImageInOrderHistory/Block/Order/History.php
<?php
/**
* TechSolve_ImageInOrderHistory
*
* PHP version 7.x
*
* @category PHP
* @package TechSolve\ImageInOrderHistory
* @author TechSolve Team
* @copyright 2020 Copyright (c) TechSolve
**/
namespace TechSolve\ImageInOrderHistory\Block\Order;
class History extends \Magento\Sales\Block\Order\History
{
/**
* [$productFactory description]
* @var [type]
*/
private $productFactory;
/**
* [$imageHelper description]
* @var [type]
*/
private $imageHelper;
/**
* [__construct description]
* @param \Magento\Framework\View\Element\Template\Context $context [description]
* @param \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory [description]
* @param \Magento\Customer\Model\Session $customerSession [description]
* @param \Magento\Sales\Model\Order\Config $orderConfig [description]
* @param array $data [description]
* @param \Magento\Catalog\Model\ProductFactory $productFactory [description]
* @param \Magento\Catalog\Helper\Image $imageHelper [description]
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
\Magento\Customer\Model\Session $customerSession,
\Magento\Sales\Model\Order\Config $orderConfig,
array $data = [],
\Magento\Catalog\Model\ProductFactory $productFactory,
\Magento\Catalog\Helper\Image $imageHelper
)
{
parent::__construct($context,$orderCollectionFactory,$customerSession,$orderConfig,$data);
$this->productFactory = $productFactory;
$this->imageHelper = $imageHelper;
}
/**
* [getProductImage description]
* @param [type] $pid [description]
* @return [type] [description]
*/
public function getProductImage($pid){
$product = $this->productFactory->create()->load($pid);
return $this->imageHelper->init($product, 'product_page_image_small')->setImageFile($product->getImage())->resize(160, 160)->getUrl();
}
}
Now call this function from your's own history.phtml template
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// phpcs:disable Magento2.Templates.ThisInTemplate
/** @var \Magento\Sales\Block\Order\History $block */
?>
<?php $_orders = $block->getOrders(); ?>
<?= $block->getChildHtml('info') ?>
<?php if ($_orders && count($_orders)) : ?>
<?php foreach ($_orders as $_order) : ?>
<div class="order-row row align-items-center" onclick="window.location = '<?= $block->escapeUrl($block->getViewUrl($_order)) ?>'">
<div class="order-row-properties col-sm-3">
<a href="<?= $block->escapeUrl($block->getViewUrl($_order)) ?>">
<strong class="order-row-date"><?= $block->escapeHtml($_order->getRealOrderId()) ?> - <?= $block->formatDate($_order->getCreatedAt(), \IntlDateFormatter::LONG) ?></strong>
</a>
<p class="order-row-status"><?= $block->escapeHtml($_order->getStatusLabel()) ?></p>
</div>
<div class="order-row-list col-sm-8">
<ul class="">
<?php
$items = $_order->getAllVisibleItems();
$item = array_slice($items, 0, 3);
foreach($item as $itm): ?>
<?php
$image_URl = $block->getProductImage($itm->getProductId()); ?>
<li class="order-row-item">
<div class="order-row-product">
<div class="order-row-product-image">
<img src="<?= $image_URl;?>" border="0" alt="order-product-image" />
</div>
<div class="order-row-product-name">
<?= substr($block->escapeHtml($itm->getName()), 0, 20) ?>
</div>
</div>
</li>
<?php endforeach;?>
</ul>
</div>
<div class="order-row-icon col-sm-1">
<i class="fal fa-chevron-right"></i>
</div>
</div>
<?php endforeach;?>
<?php else : ?>
<div class="message info empty"><span><?= $block->escapeHtml(__('You have placed no orders.')) ?></span></div>
<?php endif ?>