Question

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; ?>
Was it helpful?

Solution

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 ?>

OTHER TIPS

**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 ?>
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top