Magento 2 二次开发:添加产品图片显示在订单列表中

7天成为Magento系统架构师,现在开始学习Magento全栈开发!

《Magento2.X企业级开发实战》

在本教程中,我们将使用插件(拦截器)技术将额外的列产品图像显示在订单列表中。
有关插件(拦截器)的更多信息:
https://devdocs.magento.com/guides/v2.3/extension-dev-guide/plugins.html?source=pepperjam&publisherId=96525&clickId=2614425708

如果您在 vendor/magento/module-sales/view/adminhtml/layout/sales_order_view.xml 中打开 sales_order_view.xml
你会发现这段代码:

    <block class="Magento\Sales\Block\Adminhtml\Order\View\Items" name="order_items" template="Magento_Sales::order/view/items.phtml">
                        <arguments>
                            <argument name="columns" xsi:type="array">
                                <item name="product" xsi:type="string" translate="true">Product</item>
                                <item name="status" xsi:type="string" translate="true">Item Status</item>
                                <item name="price-original" xsi:type="string" translate="true">Original Price</item>
                                <item name="price" xsi:type="string" translate="true">Price</item>
                                <item name="ordered-qty" xsi:type="string" translate="true">Qty</item>
                                <item name="subtotal" xsi:type="string" translate="true">Subtotal</item>
                                <item name="tax-amount" xsi:type="string" translate="true">Tax Amount</item>
                                <item name="tax-percent" xsi:type="string" translate="true">Tax Percent</item>
                                <item name="discont" xsi:type="string" translate="true">Discount Amount</item>
                                <item name="total" xsi:type="string" translate="true">Row Total</item>
                            </argument>
                        </arguments>
                        <block class="Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\DefaultRenderer" as="default" name="default_order_items_renderer" template="Magento_Sales::order/view/items/renderer/default.phtml">
                            <arguments>
                                <argument name="columns" xsi:type="array">
                                    <item name="product" xsi:type="string" translate="false">col-product</item>
                                    <item name="status" xsi:type="string" translate="false">col-status</item>
                                    <item name="price-original" xsi:type="string" translate="false">col-price-original</item>
                                    <item name="price" xsi:type="string" translate="false">col-price</item>
                                    <item name="qty" xsi:type="string" translate="false">col-ordered-qty</item>
                                    <item name="subtotal" xsi:type="string" translate="false">col-subtotal</item>
                                    <item name="tax-amount" xsi:type="string" translate="false">col-tax-amount</item>
                                    <item name="tax-percent" xsi:type="string" translate="false">col-tax-percent</item>
                                    <item name="discont" xsi:type="string" translate="false">col-discont</item>
                                    <item name="total" xsi:type="string" translate="false">col-total</item>
                                </argument>
                            </arguments>
                        </block>
                    </block>

项目列和渲染器已通过参数注入,我们有 2 个类负责:
Magento\Sales\Block\Adminhtml\Order\View\Items 添加列,以及 Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\DefaultRenderer 向我们的每个列添加自定义渲染器。
这两个类具有以下功能:

 public function getColumns()
    {
        $columns = array_key_exists('columns', $this->_data) ? $this->_data['columns'] : [];
        return $columns;
    }

它从布局中读取列并将其添加到 .
但是 DefaultRenderer 类还有其他功能负责使用海关 HTML 渲染器;

public function getColumnHtml(\Magento\Framework\DataObject $item, $column, $field = null)
    {
        $html = '';
        switch ($column) {
            case 'product':
                if ($this->canDisplayContainer()) {
                    $html .= '<div id="' . $this->getHtmlId() . '">';
                }
                $html .= $this->getColumnHtml($item, 'name');
                if ($this->canDisplayContainer()) {
                    $html .= '</div>';
                }
                break;
            case 'status':
                $html = $item->getStatus();
                break;
            case 'price-original':
                $html = $this->displayPriceAttribute('original_price');
                break;
            case 'tax-amount':
                $html = $this->displayPriceAttribute('tax_amount');
                break;
            case 'tax-percent':
                $html = $this->displayTaxPercent($item);
                break;
            case 'discont':
                $html = $this->displayPriceAttribute('discount_amount');
                break;
            default:
                $html = parent::getColumnHtml($item, $column, $field);
        }
        return $html;
    }

让我们开始在路径 app/code/Ibnab/OrderItemsImage/etc/adminhtml/di.xml push 中的 di.xml 中注入我们的插件(拦截器):

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Block\Adminhtml\Order\View\Items">
        <plugin name="imageitem_order_prepare_data_source_after" type="Ibnab\OrderItemsImage\Plugin\Adminhtml\AddImage"/>
    </type>
    <type name="Magento\Sales\Block\Adminhtml\Order\View\Items\Renderer\DefaultRenderer">
        <plugin name="imagerenderer_order_prepare_data_source_before_around" type="Ibnab\OrderItemsImage\Plugin\Adminhtml\AddRenderer"/>
    </type>
</config>

我们的第一个插件(拦截器)Ibnab\OrderItemsImage\Plugin\Adminhtml\AddImage 应用于类 Magento\Sales\Block\Adminhtml\Order\View\Items 并将通过使用 after 方法观察 getColumns() ,在我们的类 Ibnab\OrderItemsImage\ 中 Plugin\Adminhtml\AddImage 添加:

<?php
namespace Ibnab\OrderItemsImage\Plugin\Adminhtml;
class AddImage {
  /**
     * @param ContextInterface $context
     * @param Url $urlBuilder
     */
    public function __construct(
    ) {
    }
    public function afterGetColumns($items, $result) {
      if (is_array($result)) {
            $newResult['image'] = 'Image';
            foreach($result as $key=>$value){
              $newResult[$key]  = $value;
            }
            $result = $newResult;
        }
     return $result;
    }
}

很简单 before after 方法获取结果并将我们的图像添加为数组的第一行:

$newResult['image'] = 'Image';
            foreach($result as $key=>$value){
              $newResult[$key]  = $value;
            }
            $result = $newResult;
 

现在在 Ibnab\OrderItemsImage\Plugin\Adminhtml\AddRenderer(负责海关渲染器的插件)中添加:

<?php
namespace Ibnab\OrderItemsImage\Plugin\Adminhtml;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
class AddRenderer {
    /*
     * @var UrlInterface
     */
    protected $_imageHelper;
    protected $_coreRegistry = null;
    /**
     * @param ContextInterface $context
     * @param Url $urlBuilder
     */
    public function __construct(
     \Magento\Framework\Registry $registry, \Ibnab\OrderItemsImage\Helper\Image $imageHelper
    ) {
        $this->_coreRegistry = $registry;
        $this->_imageHelper = $imageHelper;
    }
    public function afterGetColumns($defaultRenderer, $result) {
        if (is_array($result)) {
            $newResult['image'] = 'col-image';
            foreach ($result as $key => $value) {
                $newResult[$key] = $value;
            }
            $result = $newResult;
        }
        return $result;
    }
    public function beforeGetColumnHtml($defaultRenderer, \Magento\Framework\DataObject $item, $column, $field = null) {
        $html = '';
        switch ($column) {
            case 'image':
                $this->_coreRegistry->register('is_image_renderer', 1);
                $this->_coreRegistry->register('ibnab_current_order_item', $item);
                break;
        }
        return [$item, $column, $field];
    }
    public function afterGetColumnHtml($defaultRenderer, $result) {
        $is_image = $this->_coreRegistry->registry('is_image_renderer');
        $currentItem = $this->_coreRegistry->registry('ibnab_current_order_item');
        $this->_coreRegistry->unregister('is_image_renderer');
        $this->_coreRegistry->unregister('ibnab_current_order_item');
        if ($is_image == 1) {
            return  $this->renderImage($currentItem->getProduct());
        }
        return $result;
    }
    protected function renderImage($product) {
        $this->_imageHelper->addGallery($product);
        $images = $this->_imageHelper->getGalleryImages($product);
        foreach ($images as $image) {
            $item = $image->getData();
            if (isset($item['media_type']) && $item['media_type'] == 'image') {
            $imgPath = isset($item['small_image_url']) ? $item['small_image_url'] : null;    
            return "<img src=".$imgPath." alt=".$product->getName().">";
            }
        }
        return null;
   }
}

有点复杂,我们将两个参数推送到构造函数 \Magento\Framework\Registry $registry, \Ibnab\OrderItemsImage\Helper\Image $imageHelper 我们将在每个函数中看到实用程序让我们开始:

 public function afterGetColumns($defaultRenderer, $result) {
        if (is_array($result)) {
            $newResult['image'] = 'col-image';
            foreach ($result as $key => $value) {
                $newResult[$key] = $value;
            }
            $result = $newResult;
        }
        return $result;
 }
 

很容易我们将自定义渲染器添加到我们的列图像 $newResult[‘image’] = ‘col-image’;
和内部功能:

 public function beforeGetColumnHtml($defaultRenderer, \Magento\Framework\DataObject $item, $column, $field = null) {
        $html = '';
        switch ($column) {
            case 'image':
                $this->_coreRegistry->register('is_image_renderer', 1);
                $this->_coreRegistry->register('ibnab_current_order_item', $item);
                break;
        }
        return [$item, $column, $field];
    }

我们刚刚添加到 register 以表明我们的列图像和项目父项已通过 foreach 语句传递给函数 getColumnHtml 以在 afterGetColumnHtml 中使用:

 public function afterGetColumnHtml($defaultRenderer, $result) {
        $is_image = $this->_coreRegistry->registry('is_image_renderer');
        $currentItem = $this->_coreRegistry->registry('ibnab_current_order_item');
        $this->_coreRegistry->unregister('is_image_renderer');
        $this->_coreRegistry->unregister('ibnab_current_order_item');
        if ($is_image == 1) {
            return  $this->renderImage($currentItem->getProduct());
        }
        return $result;
    }

此函数的作用是检测系统现在正在尝试渲染我们的图像列,因此我们通过自定义渲染器进行干预以自定义结果 return $this->renderImage($currentItem->getProduct()); , $item 是 Magento\Sales\Model\Order\Item 的实例并且具有函数 getProduct :

 protected function renderImage($product) {
        $this->_imageHelper->addGallery($product);
        $images = $this->_imageHelper->getGalleryImages($product);
        foreach ($images as $image) {
            $item = $image->getData();
            if (isset($item['media_type']) && $item['media_type'] == 'image') {
            $imgPath = isset($item['small_image_url']) ? $item['small_image_url'] : null;    
            return "<img src=".$imgPath." alt=".$product->getName().">";
            }
        }
        return null;
    }

好的 $this->_imageHelper 是 \Ibnab\OrderItemsImage\Helper\Image 的一个实例,我们已经添加以获取产品的图像:

<?php
namespace Ibnab\OrderItemsImage\Helper;
use Magento\Catalog\Model\Product\Gallery\ReadHandler as GalleryReadHandler;
class Image extends \Magento\Framework\App\Helper\AbstractHelper {
  protected $galleryReadHandler;
    /**
     * Catalog Image Helper
     *
     * @var \Magento\Catalog\Helper\Image
     */
    protected $imageHelper;
    public function __construct(
    GalleryReadHandler $galleryReadHandler,  \Magento\Framework\App\Helper\Context $context,\Magento\Catalog\Helper\Image $imageHelper)
    {
        $this->imageHelper = $imageHelper;
        $this->galleryReadHandler = $galleryReadHandler;
        parent::__construct($context);
    }
   /** Add image gallery to $product */
    public function addGallery($product) {
        $this->galleryReadHandler->execute($product);
    }
    public function getGalleryImages(\Magento\Catalog\Api\Data\ProductInterface $product)
    {
        $images = $product->getMediaGalleryImages();
        if ($images instanceof \Magento\Framework\Data\Collection) {
            foreach ($images as $image) {
                /** @var $image \Magento\Catalog\Model\Product\Image */
                $image->setData(
                    'small_image_url',
                    $this->imageHelper->init($product, 'product_page_image_small')
                        ->setImageFile($image->getFile())
                        ->getUrl()
               );
            }
        }
        return $images;
    }
}

是从产品中提取图像的通用类,您可以获得’small_image_url’或’medium_image_url’……

回到我们插件中的 renderImage($product) 函数:

 $this->_imageHelper->addGallery($product);
        $images = $this->_imageHelper->getGalleryImages($product);
        foreach ($images as $image) {
            $item = $image->getData();
            if (isset($item['media_type']) && $item['media_type'] == 'image') {
            $imgPath = isset($item['small_image_url']) ? $item['small_image_url'] : null;    
            return "<img src=".$imgPath." alt=".$product->getName().">";
            }
        }

with for foreach 语句和 if (isset($item[‘media_type’]) && $item[‘media_type’] == ‘image’) { 我们返回了 gallery 的第一张小图片。

如无特殊说明或标注,任何个人或组织,复制、转载、采集本站内容请注明:
本文来源于:【Magento中文网】,并添加本文地址链接。
如未按上述操作复制或转载,本站有权追究法律责任。
若本站内容侵犯了原著者的合法权益,可联系我们进行处理。