Как создать собственный виджет в 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!