Як додати зображення продукту на сторінці створення замовлення адміністратора у Magento 2?

10 Червня 2024

наступна стаття
Олег Літвінчук

Backend Developer

Олег  Літвінчук
Як додати зображення продукту на сторінці створення замовлення адміністратора у Magento 2?

Про автора: Олег Літвінчук, бекенд-розробник з великим досвідом роботи з проектами eCommerce на різних CMS, включно з Magento 2. На його переконання, завжди краще вкласти більше в розробку й створити досконалі ефективні інструменти, ніж ігнорувати труднощі, від яких страждатиме персонал компанії та бізнес загалом.


Зображення є невід’ємною складовою будь-якого сайту, що продає товари чи послуги. Для матеріальних продуктів це must have — адже ніхто не хоче купувати “кота в мішку” та прагне бачити те, що має отримати від угоди з інтернет-магазином. Для нематеріальних продуктів, на кшталт, послуг, тематичні зображення також важливі, оскільки створюють асоціативний ряд для замовника, що посилює бажання придбати саме тут та зараз. Але не менш важливими зображення продуктів є і для співробітників компанії, які безпосередньо оформлюють замовлення клієнтів.

Замовлення у Magento 2

Безумовно, Magento 2 є однією з кращих CMS у світі для розвитку великих проектів eCommerce. Це потужна й гнучка система, що може бути кастомізована суто під потреби вашого бізнесу до найменших деталей. Однак серед базових функцій ви не зможете знайти абсолютно все, що потрібно саме вашому бізнесові, адже автори CMS не можуть здогадуватися про думки користувачів на відстані. Тому це питання вирішують розробники, які доповнюють функціонал чи кастомізують окремі його частини.

magento-2-order-grid.png

Magento 2 найкраще підходить для розробки eCommerce проектів, де замовлення від клієнтів є основою для діяльності компанії. Адміністратори сайту отримують споівщення про нове замовлення у дашборді та можуть переглядати різноманітні деталі: дані покупця, суму оплати, назву товару та його характеристики, артикул та багато іншого. Однак побачити, що придбав користувач, у базовій версії CMS неможливо, оскільки вивід прикріплених світлин продукту не передбачений. Тому, якщо вам необхідно виводити у адмінпанель зображення, слід звернутися до коду й створити невеликий модуль — доповнення до системи, що розширює її функції. І зараз я покажу, як це робиться. 

Модуль для показу зображень продукту

Модулі для Magento 2 можуть виконувати будь-які функції, однак для коректної роботи кожного з них слід дотримуватися передбачених правил. Давайте покроково виконаємо необхідні дії для створення нового модуля.

Крок 1

Своріть файл app\code\Avivi\ProductImageAdminOrder\registration.php і використайте наведений нижче код:

1
2
3
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="\Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid" type="Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\OverrideOrder\Create\Search\Grid"/>
</config>

Крок 2

Створюємо наступний файл app\code\Avivi\ProductImageAdminOrder\etc\module.xml і використайте наведений нижче код:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<?php

namespace Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\OverrideOrder\Create\Search;

use Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\DataProvider\ProductCollection;
use Magento\Framework\App\ObjectManager;

/**
 * Adminhtml sales order create search products block
 *
 */
class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
{
    /**
     * Sales config
     *
     * @var \Magento\Sales\Model\Config
     */
    protected $_salesConfig;

    /**
     * Session quote
     *
     * @var \Magento\Backend\Model\Session\Quote
     */
    protected $_sessionQuote;

    /**
     * Catalog config
     *
     * @var \Magento\Catalog\Model\Config
     */
    protected $_catalogConfig;

    /**
     * Product factory
     *
     * @var \Magento\Catalog\Model\ProductFactory
     */
    protected $_productFactory;

    /**
     * @var ProductCollection $productCollectionProvider
     */
    private $productCollectionProvider;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Backend\Helper\Data $backendHelper
     * @param \Magento\Catalog\Model\ProductFactory $productFactory
     * @param \Magento\Catalog\Model\Config $catalogConfig
     * @param \Magento\Backend\Model\Session\Quote $sessionQuote
     * @param \Magento\Sales\Model\Config $salesConfig
     * @param array $data
     * @param ProductCollection|null $productCollectionProvider
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Backend\Helper\Data $backendHelper,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        \Magento\Catalog\Model\Config $catalogConfig,
        \Magento\Backend\Model\Session\Quote $sessionQuote,
        \Magento\Sales\Model\Config $salesConfig,
        array $data = [],
        ProductCollection $productCollectionProvider = null
    ) {
        $this->_productFactory = $productFactory;
        $this->_catalogConfig = $catalogConfig;
        $this->_sessionQuote = $sessionQuote;
        $this->_salesConfig = $salesConfig;
        $this->productCollectionProvider = $productCollectionProvider
            ?: ObjectManager::getInstance()->get(ProductCollection::class);
        parent::__construct($context, $backendHelper, $data);
    }

    /**
     * Constructor
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('sales_order_create_search_grid');
        $this->setRowClickCallback('order.productGridRowClick.bind(order)');
        $this->setCheckboxCheckCallback('order.productGridCheckboxCheck.bind(order)');
        $this->setRowInitCallback('order.productGridRowInit.bind(order)');
        $this->setDefaultSort('entity_id');
        $this->setFilterKeyPressCallback('order.productGridFilterKeyPress');
        $this->setUseAjax(true);
        if ($this->getRequest()->getParam('collapse')) {
            $this->setIsCollapsed(true);
        }
    }

    /**
     * Retrieve quote store object
     *
     * @return \Magento\Store\Model\Store
     */
    public function getStore()
    {
        return $this->_sessionQuote->getStore();
    }

    /**
     * Retrieve quote object
     *
     * @return \Magento\Quote\Model\Quote
     */
    public function getQuote()
    {
        return $this->_sessionQuote->getQuote();
    }

    /**
     * Add column filter to collection
     *
     * @param \Magento\Backend\Block\Widget\Grid\Column $column
     * @return $this
     */
    protected function _addColumnFilterToCollection($column)
    {
        // Set custom filter for in product flag
        if ($column->getId() == 'in_products') {
            $productIds = $this->_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', ['in' => $productIds]);
            } else {
                if ($productIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', ['nin' => $productIds]);
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }

    /**
     * Prepare collection to be displayed in the grid
     *
     * @return $this
     */
    protected function _prepareCollection()
    {

        $attributes = $this->_catalogConfig->getProductAttributes();
        $store = $this->getStore();

        /* @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
        $collection = $this->productCollectionProvider->getCollectionForStore($store);
        $collection->addAttributeToSelect(
            $attributes
        );
        $collection->addAttributeToFilter(
            'type_id',
            $this->_salesConfig->getAvailableProductTypes()
        );

        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    /**
     * Prepare columns
     *
     * @return $this
     */
    protected function _prepareColumns()
    {
        $this->addColumn(
            'thumbnail',
            [
                'filter' => false,
                'sortable' => false,
                'header' => __('Images'),
                'name' => 'thumbnail',
                'inline_css' => 'thumbnail',
                'index' => 'image',
                'class' => 'image',
                'renderer' => 'Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\Product\Grid\Renderer\Image',
            ]
        );
        $this->addColumn(
            'entity_id',
            [
                'header' => __('ID'),
                'sortable' => true,
                'header_css_class' => 'col-id',
                'column_css_class' => 'col-id',
                'index' => 'entity_id'
            ]
        );
        $this->addColumn(
            'name',
            [
                'header' => __('Product'),
                'renderer' => \Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\Renderer\Product::class,
                'index' => 'name'
            ]
        );
        $this->addColumn('sku', ['header' => __('SKU'), 'index' => 'sku']);
        $this->addColumn(
            'price',
            [
                'header' => __('Price'),
                'column_css_class' => 'price',
                'type' => 'currency',
                'currency_code' => $this->getStore()->getCurrentCurrencyCode(),
                'rate' => $this->getStore()->getBaseCurrency()->getRate($this->getStore()->getCurrentCurrencyCode()),
                'index' => 'price',
                'renderer' => \Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\Renderer\Price::class
            ]
        );

        $this->addColumn(
            'in_products',
            [
                'header' => __('Select'),
                'type' => 'checkbox',
                'name' => 'in_products',
                'values' => $this->_getSelectedProducts(),
                'index' => 'entity_id',
                'sortable' => false,
                'header_css_class' => 'col-select',
                'column_css_class' => 'col-select'
            ]
        );

        $this->addColumn(
            'qty',
            [
                'filter' => false,
                'sortable' => false,
                'header' => __('Quantity'),
                'renderer' => \Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\Renderer\Qty::class,
                'name' => 'qty',
                'inline_css' => 'qty',
                'type' => 'input',
                'validate_class' => 'validate-number',
                'index' => 'qty'
            ]
        );

        return parent::_prepareColumns();
    }

    /**
     * Get grid url
     *
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl(
            'sales/*/loadBlock',
            ['block' => 'search_grid', '_current' => true, 'collapse' => null]
        );
    }

    /**
     * Get selected products
     *
     * @return mixed
     */
    protected function _getSelectedProducts()
    {
        $products = $this->getRequest()->getPost('products', []);

        return $products;
    }

    /**
     * Add custom options to product collection
     *
     * @return $this
     */
    protected function _afterLoadCollection()
    {
        $this->getCollection()->addOptionsToResult();
        return parent::_afterLoadCollection();
    }
}

Крок 3

Отож ми вже майже поруч нашої мети! Тепер створюємо наступний файл app\code\Avivi\ProductImageAdminOrder\Block\Adminhtml\OverrideOrder\Create\Search\Grid.php використовуючи наведений нижче код:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
namespace Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\Product\Grid\Renderer;

use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\Asset\Repository;
use Magento\Catalog\Helper\ImageFactory;
use Magento\Framework\Image\AdapterFactory;
use Magento\Store\Model\StoreManager;
use Magento\Store\Model\ScopeInterface;

class Image extends AbstractRenderer
{
    private $_storeManager;
    private $helperImageFactory;
    private $assetRepos;
    private $adapterFactory;
    private $scopeConfig;
    private $storeManager;
    /**
     * @param \Magento\Backend\Block\Context $context
     * @param array $data
     */
    public function __construct(\Magento\Backend\Block\Context $context,
                                Repository $assetRepos,
                                ImageFactory $helperImageFactory,
                                AdapterFactory $adapterFactory,
                                StoreManager $storeManager,
                                StoreManagerInterface $storemanager, array $data = [])
    {
        $this->_storeManager = $storemanager;
        $this->assetRepos = $assetRepos;
        $this->helperImageFactory = $helperImageFactory;
        $this->adapterFactory = $adapterFactory;
        $this->storeManager = $storeManager;
        $this->scopeConfig = $context->getScopeConfig();

        parent::__construct($context, $data);
        $this->_authorization = $context->getAuthorization();
    }
    /**
     * Renders grid column
     *
     * @param Object $row
     * @return  string
     */
    public function render(DataObject $row)
    {
        $mediaDirectory = $this->_storeManager->getStore()->getBaseUrl(
            \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
        );

        if($this->_getValue($row)){
            $imageUrl = $mediaDirectory.'/catalog/product'.$this->_getValue($row);
        }else{
            $plUrl = $this->scopeConfig->getValue('catalog/placeholder/thumbnail_placeholder',ScopeInterface::SCOPE_STORE,0);
            $imageUrl = $mediaDirectory.'/catalog/product/placeholder/'.$plUrl;
        }
        return '<img src="'.$imageUrl.'" style="width: 5rem;border: 1px solid #d6d6d6;"/>';

    }
}

 

Крок 4. Останній

Наостанок створюємо файл app\code\Avivi\ProductImageAdminOrder\Block\Adminhtml\Product\Grid\Renderer\Image.php і використайте наведений нижче код:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
namespace Avivi\ProductImageAdminOrderCreate\Block\Adminhtml\Product\Grid\Renderer;

use Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer;
use Magento\Framework\DataObject;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\Asset\Repository;
use Magento\Catalog\Helper\ImageFactory;
use Magento\Framework\Image\AdapterFactory;
use Magento\Store\Model\StoreManager;
use Magento\Store\Model\ScopeInterface;

class Image extends AbstractRenderer
{
    private $_storeManager;
    private $helperImageFactory;
    private $assetRepos;
    private $adapterFactory;
    private $scopeConfig;
    private $storeManager;
    /**
     * @param \Magento\Backend\Block\Context $context
     * @param array $data
     */
    public function __construct(\Magento\Backend\Block\Context $context,
                                Repository $assetRepos,
                                ImageFactory $helperImageFactory,
                                AdapterFactory $adapterFactory,
                                StoreManager $storeManager,
                                StoreManagerInterface $storemanager, array $data = [])
    {
        $this->_storeManager = $storemanager;
        $this->assetRepos = $assetRepos;
        $this->helperImageFactory = $helperImageFactory;
        $this->adapterFactory = $adapterFactory;
        $this->storeManager = $storeManager;
        $this->scopeConfig = $context->getScopeConfig();

        parent::__construct($context, $data);
        $this->_authorization = $context->getAuthorization();
    }
    /**
     * Renders grid column
     *
     * @param Object $row
     * @return  string
     */
    public function render(DataObject $row)
    {
        $mediaDirectory = $this->_storeManager->getStore()->getBaseUrl(
            \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
        );

        if($this->_getValue($row)){
            $imageUrl = $mediaDirectory.'/catalog/product'.$this->_getValue($row);
        }else{
            $plUrl = $this->scopeConfig->getValue('catalog/placeholder/thumbnail_placeholder',ScopeInterface::SCOPE_STORE,0);
            $imageUrl = $mediaDirectory.'/catalog/product/placeholder/'.$plUrl;
        }
        return '<img src="'.$imageUrl.'" style="width: 5rem;border: 1px solid #d6d6d6;"/>';

    }
}
>

 

Зберігаємо всі зміни та перевіряємо результат. Тепер зовнішній вигляд переліку замовлень у адмінпанель вашого Magento 2 змінився — додалася колонка з мініатюрою зображення продукту:

image_2024-05-10_09-39-00.png

Як бачите, вирішити проблему шляхом створення нового модуля зовсім не страшно. Однак завжди краще довірити завдання з розробки професіоналам: я і команда Авіві завжди готові допомогти вам з розробкою проектів на Magento 2.

Baner articles 2023.png


Схожі статті
Записатись на консультацію

Ми зв'яжемось з Вами протягом 10 хвилин