1

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; ?>
1
  • i have updated history.phtml file, please check – MR.R DNATH Jun 6 '20 at 13:45
1
+50

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 ?>
12
  • Thanks Herve! See my update what I tried, but that does not seem to load the image when loading this on the history.phtml template. – JGeer Jun 1 '20 at 17:09
  • I can't see the function buildImage, also are you able to add a snippet of your template to see how you use it? – Herve Tribouilloy Jun 1 '20 at 17:13
  • Thanks! See my edit, forgot the buildImage in my question. – JGeer Jun 1 '20 at 17:32
  • Any idea what I am missing here? – JGeer Jun 4 '20 at 8:32
  • Have you tried the module? I have changed the answer completely.. I thought you had noticed – Herve Tribouilloy Jun 4 '20 at 8:38
0
**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 ?>
4
  • Thanks! Tried it but it does not seem to work. Mainly because inside the foreach to load orders, we load a foreach to load the items see: <?php $items = $_order->getAllVisibleItems(); $item = array_slice($items, 0, 3); foreach($item as $itm): ?> Any idea? – JGeer Jun 5 '20 at 9:13
  • If you need product details , you don't need to do getAllVisibleItems().-->in foreach you just run one more foreach that is not good practice. you can get product id by $_order->getProductId(); – MR.R DNATH Jun 5 '20 at 9:54
  • i have updated history.phtml file, please check & let me know – MR.R DNATH Jun 6 '20 at 13:46
  • Thanks! I tried the code, but it does not load the src, so for some reason it does not load the image. – JGeer Jun 9 '20 at 9:57

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.