Як створити власний віджет в Magento 2

Досить часто при роботі з Magento 2 з’являється необхідність у власному (кастомному) віджеті. По дефолту система має досить широкий набір віджетів з простим функціоналом. Однак, коли вам потрібно змінити функціональність віджета або збільшити вибір параметрів налаштування, для цього вам доведеться створити свій власний.

У сьогоднішній статті ми розглянемо на практиці, як створити віджет, який розширює функціональність системного (дефолтного) віджета. Ми будемо розширювати функціональність віджета «Список товарів каталогу», і змінимо порядок представлення товарів.

 

 

Створення модуля під новий віджет

Перш ніж ми зможемо створити віджет, нам потрібно кудись його помістити. Для цього нам знадобиться новий (або вже готовий) модуль. Інструкцію по створенню модуля в Мадженто2 ви знайдете за посиланням. Для практики ми будемо використовувати модуль app/code/Sebweo/SortProductsWidget. В папці модуля нам потрібно створити два файли: registration.php та etc/module.xml.

 

Код файлу registration.php

<?php  \Magento\Framework\Component\ComponentRegistrar::register(   \Magento\Framework\Component\ComponentRegistrar::MODULE,   'Sebweo_SortProductsWidget',   __DIR__  );  

 

Код файлу etc/module.xml

<?xml version="1.0"?>  <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">   <module name="Sebweo_SortProductsWidget" setup_version="1.0.0" >    <sequence>     <module name="Magento_CatalogWidget"/>    </sequence>   </module>  </config>  

 

 

Якщо ви читали статтю про створення модуля в Мадженто2, тут передбачається, що ви знаєте, чому ці файли повинні бути присутніми і ми не будемо заглиблюватися в їх код. Єдине, що варто відзначити, це тег <sequence> в etc/module.xml, який в основному говорить системі завантажувати модуль Magento_CatalogWidget перед нашим розширенням.



 

 

Тонке налаштування (кастомізація) віджета

Макет (layout)

Тепер, коли ми створили модуль, ми можемо почати створювати віджет. Для того, щоб створити макет віджета, ми повинні створити файл etc/widget.xml.

 

Код файлу etc/widget.xml

<?xml version="1.0" encoding="UTF-8"?>  <widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">   <widget id="sebweo_products_list" class="Sebweo\SortProductsWidget\Block\Product\ProductsList" placeholder_image="Sebweo_SortProductsWidget::images/sebweo_widget_block.png">    <label translate="true">Sorted Products List</label>    <description>Sorted Catalog Products List</description>    <parameters>     <parameter name="title" xsi:type="text" required="false" visible="true">      <label translate="true">Title</label>     </parameter>     <parameter name="products_sort_by" xsi:type="select" visible="true" source_model="Sebweo\SortProductsWidget\Model\SortBy">      <label translate="true">Sort Products By</label>     </parameter>     <parameter name="products_sort_order" xsi:type="select" visible="true" source_model="Sebweo\SortProductsWidget\Model\SortOrder">      <label translate="true">Sort Products Order</label>     </parameter>     <parameter name="show_pager" xsi:type="select" visible="true" source_model="Magento\Config\Model\Config\Source\Yesno">      <label translate="true">Display Page Control</label>     </parameter>     <parameter name="products_per_page" xsi:type="text" required="true" visible="true">      <label translate="true">Number of Products per Page</label>      <depends>       <parameter name="show_pager" value="1" />      </depends>      <value>5</value>     </parameter>     <parameter name="products_count" xsi:type="text" required="true" visible="true">      <label translate="true">Number of Products to Display</label>      <value>10</value>     </parameter>     <parameter name="template" xsi:type="select" required="true" visible="true">      <label translate="true">Template</label>      <options>       <option name="default" value="Magento_CatalogWidget::product/widget/content/grid.phtml" selected="true">        <label translate="true">Products Grid Template</label>       </option>      </options>     </parameter>     <parameter name="cache_lifetime" xsi:type="text" visible="true">      <label translate="true">Cache Lifetime (Seconds)</label>      <description translate="true">86400 by default, if not set. To refresh instantly, clear the Blocks HTML Output cache.</description>     </parameter>     <parameter name="condition" xsi:type="conditions" visible="true" required="true" sort_order="10" class="Magento\CatalogWidget\Block\Product\Widget\Conditions">      <label translate="true">Conditions</label>     </parameter>    </parameters>   </widget>  </widgets>  

 

 

Тут ми створюємо нод <widget> всередині тега <widgets>. Тег <widget> містить параметри для конфігурації нашого віджета. Ідентифікатор віджета – це унікальне ім’я, яке ви хочете використовувати для свого віджета. Це може бути що завгодно, але для цього уроку ми назвали його sebweo_products_list. Тег class – це блок, який ми створимо пізніше; він контролює, як насправді функціонує віджет (ми будемо розширювати функціональність блоку Magento/CatalogWidget/Block/Product/ProductsList). Тег placeholder_image – це просто зображення, яке відображається в редакторі WYSIWYG бекенду Magento. Це не обов’язково, але додає приємний штрих при перегляді WYSIWYG.

Всередині віджета ви можете бачити, що ми перерахували параметри, які є вхідними даними, що потрібні для WYSIWYG редактора. Кожен з цих параметрів має name, type, required та visible властивості. Ім’я (name) має бути логічним, постільки вам потрібно буде посилатися на нього в блоці віджета. Оскільки ми розширюємо базовий блок Magento, ми використовували ті ж імена, що і в системному віджеті списка товарів. Тип (type) – це просто тип введення, який ви хочете використовувати в бекенді при налаштуванні віджета. Видимість (visible) керує видимістю опції у формі під час налаштування. Усередині кожного тега параметра є тег <label>, який встановлює мітку (ярлик) для параметра. Ви також помітите, що деякі параметри мають тег <depends>. Це означає, що даний параметр буде відображатися тільки в тому випадку, якщо параметр, вказаний в тезі залежності, має значення, встановлене в цьому тезі. Деякі параметри також мають тег <value>, який встановлює значення за замовчуванням для даного параметра. Нарешті, параметри, які мають свій тип вибору (select), потребують однієї з двох речей. Їм потрібен або source_model, як вказано в наших параметрах products_sort_by і products_sort_order, або тег <options>, такий як наш template параметр.

 

 

Створення Блоку для віджета

Тепер, коли ми розібралися з файлом widget.xml, ми можемо створити файл ProductsList.php. Він повинен знаходитися за адресою Block/Product/ProductsList.php.

 

Код файлу Block/Product/ProductsList.php

<?php  namespace Sebweo\SortProductsWidget\Block\Product;  class ProductsList extends \Magento\CatalogWidget\Block\Product\ProductsList  {   const DEFAULT_SORT_BY = 'id';   const DEFAULT_SORT_ORDER = 'asc';   public function createCollection()   {    $collection = $this->productCollectionFactory->create();    $collection->setVisibility($this->catalogProductVisibility->getVisibleInCatalogIds());    $collection = $this->_addProductAttributesAndPrices($collection)     ->addStoreFilter()     ->setPageSize($this->getPageSize())     ->setCurPage($this->getRequest()->getParam($this->getData('page_var_name'), 1))     ->setOrder($this->getSortBy(), $this->getSortOrder());    $conditions = $this->getConditions();    $conditions->collectValidatedAttributes($collection);    $this->sqlBuilder->attachConditionToCollection($collection, $conditions);    return $collection;   }   public function getSortBy()   {    if (!$this->hasData('products_sort_by')) {     $this->setData('products_sort_by', self::DEFAULT_SORT_BY);    }    return $this->getData('products_sort_by');   }   public function getSortOrder()   {    if (!$this->hasData('products_sort_order')) {     $this->setData('products_sort_order', self::DEFAULT_SORT_ORDER);    }    return $this->getData('products_sort_order');   }  }  

 

 

Як ми вже згадували, ми розширюємо файл /Magento/CatalogWidget/Block/Product/ProductsList.php, тому нам не потрібно переписувати будь-які методи, які вже написані в цьому класі. Однак ми переписали функцію createCollection() і додали дві нові функції. Функція createCollection() не сильно змінилася, ми просто встановлюємо порядок відображення колекції за допомогою setOrder(). Ця функція приймає два параметри: рядок, що містить те, що ви хочете відсортувати, і рядок, що містить порядок, в якому ви хочете сортувати (по зростанню або по спадаючій).

 

Якщо ви подивіться на одну з наших нових функцій, ви побачите те, що саме вони роблять.

 

public function getSortBy()  {   if (!$this->hasData('products_sort_by')) {    $this->setData('products_sort_by', self::DEFAULT_SORT_BY);   }   return $this->getData('products_sort_by');  }  

 

 

Перше, що робить цей метод, це перевіряє, чи встановив користувач параметр віджету з ім’ям products_sort_by. Якщо ні, то він встановлює products_sort_by в значення за замовчуванням, яке ми визначили раніше в коді. Нарешті, він повертає дані, пов’язані з products_sort_by.

 

 

Створення Моделей для віджета

Тепер, коли ми створили макет нашого віджета і його Блок, ми можемо створити Моделі. Ці Моделі представляють собою файли, які призначаються як source_model для параметрів нашого віджета в макеті. Ці файли прості, їх єдине завдання – повернути масив опцій. Для цього уроку вам буде потрібно створити два файли Моделі: Model/SortBy.php та Model/SortOrder.php.

 

Код файлу Model/SortBy.php

<?php  namespace Sebweo\SortProductsWidget\Model;  class SortBy implements \Magento\Framework\Option\ArrayInterface  {   public function toOptionArray()   {    return [    ['value' => 'id', 'label' => __('Product ID')],    ['value' => 'name', 'label' => __('Name')],    ['value' => 'price', 'label' => __('Price')]    ];   }  }  

 

 

Код файлу Model/SortOrder.php

<?php  namespace Sebweo\SortProductsWidget\Model;  class SortOrder implements \Magento\Framework\Option\ArrayInterface  {   public function toOptionArray()   {    return [    ['value' => 'asc', 'label' => __('Ascending')],    ['value' => 'desc', 'label' => __('Descending')]    ];   }  }  

 

 

Ці файли мають тільки один метод: toOptionArray(). Він повертає масив можливих опцій для параметра вашого віджета. Кожен параметр має значення, яким є значення параметра, і мітку (ярлик), яку користувач бачить при перегляді параметрів.

 

 

Тестування нового віджету

Тепер, коли ми створили наш віджет, ми можемо перевірити його і переконатися, що все працює як треба. Для цього додайте віджет на головну сторінку свого інтернет-магазину. Перейдіть в адмінпанелі до WYSIWYG редактору для домашньої сторінки і додайте новий віджет. Ви повинні побачити нові налаштування, які ми додали в наш кастомний віджет.

Після того, як ви створили і налаштували новий віджет, перейдіть на головну сторінку сайту і подивіться, чи працює він! А він повинен працювати!

Вітаємо, ви щойно створили власний віджет в Magento 2!