Magento 2 二次开发:添加产品图片显示在订单列表中
《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中文网】,并添加本文地址链接。
如未按上述操作复制或转载,本站有权追究法律责任。
若本站内容侵犯了原著者的合法权益,可联系我们进行处理。