Русский блог ET

Виджеты в Magento

Вступление

Когда вышла версия Magento 1.4, разработчики из Varien заявили о том, что они облегчили работу своим пользователям, введя такое понятие как виджеты (widgets), но примеров работы с ними, как всегда, не предоставили. Поэтому программистам самим пришлось копаться в коде стандартных модулей, чтобы понять, как виджеты работают. К сожалению, судя по тому, что я вижу в модулях, появляющихся в Magento Connect, многие разработчики либо не знают про такой инструмент, либо не разобрались, либо просто не хотят его использовать.

Поэтому я бы хотел исправить эту ситуацию и рассказать о виджетах тем, кто с ними ещё не сталкивался. Если же вы уже знакомы с их созданием, эта статья для вас скорее всего не откроет ничего нового, так как рассчитана на начинающих. Но, если у вас будет, что добавить или вы захотите меня поправить, я буду вам только благодарен.

Что такое виджет?

Виджет — примитив графического интерфейса пользователя, имеющий стандартный внешний вид и выполняющий стандартные действия.

©Википедия

Согласен, данное определение не блещет конкретикой, да и не совсем корректно в случае Magento, поэтому я попытаюсь объяснить более приземлённым языком, что называют виджетом в контексте нашей платформы. Пожалуй, легче всего это будет сделать на примере.

Допустим, вы написали какой-то модуль, который будет использоваться на пользовательской части и хотите дать возможность тем, кто будет им пользоваться, выводить посетителю сайта какую-либо информацию. Ради примера возьмём модуль для ведения блога интернет-магазина и возможность вывести список последних 5 новостей. Скажем, вы допускаете, что пользователь захочет разместить блок с последними новостями на какой-либо CMS странице, всех CMS страницах или всех страницах вообще. Или, скажем, баннер в конкретной категории, опросник для покупателя на странице успешного завершения заказа, какое-либо оповещение для покупателей на всех страницах магазина – всё это примеры использования виджетов.

До Magento 1.4 вы могли только заготовить блок, а его вставка на необходимые страницы ложилась целиком на плечи конечного пользователя. Пользователю самому надо было бы искать handler для этой страницы и прописывать его в XML темы, что не так уж легко сделать неподготовленному человеку, даже если попытаться ему подробно объяснить всю последовательность действий. И это даже тогда, когда страница всего одна.

Но с приходом Magento 1.4 появилась новая возможность – виджеты. В нашем примере блок с последними новостями как раз и является виджетом – то есть независимый блок информации, который можно вставить на любую страницу, которая поддерживает этот функционал. Независимость выражается в том, что содержимое блока не зависит от остального содержимого страницы, на которой его планируют разместить.

Чтобы разместить виджет, пользователю больше не надо будет мучать вас вопросами по процедуре установки – весь процесс размещения блока происходит в административной панели и большинству людей интуитивно понятен. Но об этом в конце статьи, а для начала необходимо рассказать, как сделать элементарный виджет.

Ставим задачу

Всё же модуль блога это излишне сложно для этой статьи, поэтому давайте возьмём что-нибудь попроще. Скажем, вывод сегодняшней даты на следующих страницах: главная и список товаров. У нас в Латвии из-за особенностей законодательства любой человек может сделать скриншот страницы товара и прийти с ним в интернет-магазин. И даже несмотря на то, что цена товара могла повыситься, магазин будет обязан продать ему товар по старой цене, так как на странице не было указано, на какую дату была действительна цена. Поэтому таким простым виджетом мы сможем частично обезопасить магазин от излишне хитрых покупателей. Конечно, это не панацея и от редактировании страницы с помощью Firebug или подобного инструмента не спасёт, но всё же большую часть потенциальных проблем отсеет.

Я опущу описание процесса создания модуля – это не является целью данной статьи, да и наверняка вы об этом уже где-то читали и скорее всего умеете это делать. В любом случае вы можете скачать полный исходный код модуля по ссылке в конце статьи.

Создание виджета

Итак, мы определились с задачей и можем заняться тем, ради чего писалась эта статья – созданием виджета. По большому счёту схема работы виджета почти ничем не отличается от обычного блока, но некоторые отличия всё же есть, на которых мы сейчас и сосредоточимся. Пожалуй, главное из них состоит в том, что в нашем модуле надо создать дополнительный конфигурационный XML файл.

app/code/local/ET/SimpleWidget/etc/widget.xml

<?xml version="1.0"?>
<widgets>
    <et_date_widget type="etsimplewidget/widget" module="etsimplewidget">
        <name>Date</name>
        <description>Displays current date</description>
        <parameters>
            <title translate="label">
                <label>Title Text</label>
                <visible>1</visible>
                <type>text</type>
                <value>Some random useless text</value>
            </title>
            <format translate="label">
                <label>Date Format</label>
                <visible>1</visible>
                <type>select</type>
                <value>system</value>
                <values>
                    <default translate="label">
                        <value>system</value>
                        <label>System Date Format</label>
                    </default>
                    <locale_format translate="label">
                        <value>localized</value>
                        <label>Localized Date Format</label>
                    </locale_format>
                </values>
            </format>
            <template translate="label">
                <label>Template</label>
                <visible>1</visible>
                <type>select</type>
                <value>etsimplewidget/block.phtml</value>
                <values>
                    <default translate="label">
                        <value>etsimplewidget/block.phtml</value>
                        <label>Block</label>
                    </default>
                    <locale_format translate="label">
                        <value>etsimplewidget/inline.phtml</value>
                        <label>Inline</label>
                    </locale_format>
                </values>
            </template>
        </parameters>
    </et_date_widget>
</widgets>

Цель этого файла – дать Magento информацию о том, какие в нашем модуле есть виджеты и какие данные они принимают в качестве параметров. Виджетов в модуле может быть сколько угодно. Давайте рассмотрим самые важные части файла.

    <et_date_widget type="etsimplewidget/widget" module="etsimplewidget">

Для получения списка всех доступных виджетов Magento обрабатывает все файлы widget.xml (у всех активных модулей) и собирает их все в один. Поэтому надо дать нашему виджету уникальный идентификатор – в нашем случае это et_date_widget. Сразу необходимо указать класс блока, который соответствует этому виджету – etsimplewidget/widget, что соответствует классу ET_SimpleWidget_Block_Widget. Также надо указать модуль, к которому относится виджет.

Внутри тега parameters содержатся настройки, влияющие на содержимое виджета. Параметр template (шаблон для виджета) является обязательным – это будет видно, когда мы перейдём к вставке виджета на нужные нам страницы. Остальной же набор параметров сугубо произволен и может быть абсолютно пуст. Рассмотрим формат объявления параметра:

            <format translate="label">
                <label>Date Format</label>
                <visible>1</visible>
                <type>select</type>
                <value>system</value>
                <values>
                    <default translate="label">
                        <value>system</value>
                        <label>System Date Format</label>
                    </default>
                    <locale_format translate="label">
                        <value>localized</value>
                        <label>Localized Date Format</label>
                    </locale_format>
                </values>
            </format>

В принципе, тут всё довольно очевидно: label – название параметра, visible – его видимость. type отвечает за отображение ввода значений и его возможные значения полностью повторяют те, которые вы используете для построения формы в административной панели – text, select, multiselect и т.п. Также есть возможность создать свой тип со своим отображением и возможностью выбора. Пример можно посмотреть в widget.xml модуля Mage_Catalog (например, виджет catalog_product_link). Далее в value указывается значение параметра по умолчанию. И, наконец, для параметров типа select или multiselect указывается набор возможных значений.

Вот, собственно, мы и рассмотрели самое большое отличие виджетов от обычных блоков. Теперь нам следует создать сам блок:
app/code/local/ET/SimpleWidget/Block/Widget.php

<?php
class ET_SimpleWidget_Block_Widget 
    extends Mage_Core_Block_Template 
    implements Mage_Widget_Block_Interface 
{
    protected $_date = '';
    protected $_title = '';
    
    protected function _toHtml()
    {
        $this->_title = $this->getTitle();
        
        if ($this->getFormat() == 'localized') {
            $locale = Mage::app()->getLocale();
            $this->_date = $locale->date(new Zend_Date())->toString(
                $locale->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM)
            );
        } else {
            $this->_date = date('Y-m-d');
        }
        
        return parent::_toHtml();
    }
}

Блок элементарен, но на некоторые вещи необходимо обратить внимание. Во-первых, если блок используется как виджет, он обязательно должен реализовывать интерфейс Mage_Widget_Block_Interface – без этого ваш виджет либо не отобразится, либо Magento выведет соответствующую ошибку. Во-вторых, Magento передаёт в виджет значения параметров только перед вызовом метода _toHtml(), поэтому вы будете вынуждены работать с параметрами именно в этой функции. Ну и в-третьих – значения параметров передаются в свойстве класса _data, поэтому вы можете получить их все вместе наверняка знакомым вам методом getData() или по одиночке – getTitle() и getFormat().

Но, возможно вы спросите, почему в блоке мы используем только 2 из 3 объявленных параметров. Что же с параметром template? Как я уже говорил выше, этот параметр является зарезервированным – Magento сама знает, когда и как его использовать.

Теперь остаётся только создать шаблоны block.phtml и inline.phtml. Так как в них нет ничего принципиально отличного от шаблонов для пустых блоков, я не буду засорять статью лишним кодом. Просто допустим, что block.phtml выводит время в виде блока с красной рамкой, а inline.phtml выводит содержимое жирным шрифтом.

Вот и всё, мы готовы перейти к вставке виджета на страницы.

Вставка виджета

Несложно догадаться, что размещение виджета пользователем происходит в административной панели. Но существуют как минимум 2 способа вставить виджет на нужную страницу. Каждый из них следует использовать для своей цели.

Вставка через WYSIWYG редактор

Этот метод стоит использовать, если вам необходимо вставить виджет в определённую часть содержимого CMS страницы, CMS блока или чего угодно, где поддерживается WYSIWYG редактор.

Просто откройте редактирование необходимой страницы или блока, поставьте курсор на то место текста, куда хотите вставить виджет и нажмите на Кнопка вставки виджета в WYSIWYG редакторе – вторую кнопку в панели инструментов редактора. Перед вами откроется форма выбора виджета. После выбора нашего Date, вы увидите все указанные в widget.xml параметры.
Форма добавления виджета в WYSIWYG редакторе
После нажатия на кнопку Insert Widget в редактор вставится следующий код:
{{widget type="etsimplewidget/widget" title="The offer is available on" format="localized" template="etsimplewidget/block.phtml"}}
Когда пользователь зайдёт на эту страницу, Magento увидит, что она должна использовать виджет. А дальше всё, как с обычными блоками: создаётся экземпляр указанного класса, в него передаются параметры title, format и template, а затем вызывается метод toHtml, который уже генерирует конечный HTML.

Массовая вставка

Что же делать, если первый способ вам не подходит. Обычно это бывает в следующих случаях:

  1. Вам необходимо вставить виджет на страницу, для которой WYSIWYG редактор не доступен
  2. Вам необходимо вставить виджет с одними и теми же параметрами на несколько страниц, и вы не хотите повторять вышеописанную процедуру несколько раз, так как это неэффективно
  3. Вам необходимо вставить виджет не в основное содержимое, а в шапку, футер, левую колонку и т.п.

В отличие от предыдущего, данный способ позволит вам всё это сделать, однако у него тоже есть свои ограничения. К сожалению, с его помощью у вас не получится вставить виджет между, скажем, первым и вторым абзацами CMS страницы – только после всего содержимого. И второе ограничение – вы не сможете вставить виджет на одну конкретную CMS страницу (домашняя страница – исключение). В этих случаях сразу выбирайте первый способ.

Итак, выберите в меню CMS -> Widgets и нажмите на кнопку Add New Widget Instance. Первый шаг создания экземпляра виджета – выбор, какой тип виджета необходимо вставить и какую тему использовать. Здесь нам следует выбрать наш виджет Date.
Выбор виджета
На втором шаге нам уже видна основная форма создания виджета. Она состоит из 2 закладок: общие для всех виджетов и специфичные для нашего Date параметры. Первая закладка в свою очередь также делится на 2 части:
Общие настройки
В этой части содержатся общие настройки, часть из которых уже нельзя изменить. Если вы перепутали тип виджета на первом шаге, вам придётся повторить всю процедуру заново. Вы можете изменить только название экземпляра, витрины, на которых надо отображать виджет, а также позиция сортировки. Название необходимо лишь для того, чтобы вы могли отличать конкретные экземпляры виджета друг от друга в общем списке. Позиция сортировки играет роль, когда в рамках одного контейнера ваш виджет конкурирует с каким-нибудь другим.
Настройки отображения виджета
А вот здесь находится как раз то самое интересное, ради чего и стоит обратить внимание на этот способ. С помощью этих настроек вы можете добавить свой экземпляр либо на все, либо на какие-то конкретные страницы. Вплоть до конкретной категории или товара. Причём, сделать это можно в совершенно разных контейнерах и разными шаблонами. На изображении вы видите, как выводить нашу дату только в шапке на главной и левой колонке в списке товаров. Кстати, шаблоны, доступные для выбора – именно те, которые мы прописали в widget.xml. В случае, если возможен только один шаблон, Magento выберет его по умолчанию.

Теперь перейдём ко второй закладке – специфичные для нашего виджета настройки. Здесь вы видите все параметры, которые мы указали в widget.xml. Разумеется, все, кроме шаблона, так как он уже сыграл свою роль в первой закладке.
Специфичные настройки
Вот, пожалуй, и всё. Остаётся только нажать на Save и посмотреть результат своего труда:
Конечный результат

Всё это прекрасно работает, если вам нужно вставить виджет с одними и теми же параметрами на всех необходимых страницах. Если же на одних страницах вам нужны одни значения параметров, а на других – другие, вам следует создать два экземпляра вашего виджета.

Итоги

Виджеты являются мощным инструментом, позволяющим сэкономить клиентам время, а значит и деньги. Помимо этого, с помощью виджетов можно легко сделать то, для чего придётся приложить определённые усилия, используя другие методы. Например, вам будет не так просто разместить что-то на странице конкретной категории или товара. Да, есть Layout Updates для категорий и товаров, но, если в магазине таких товаров или блоков несколько, вам или вашему клиенту придётся держать в голове, в какие товары он добавлял тот или иной блок. Здесь же, зайдя в редактирование виджета, вы сразу можете видеть, где он выводится.

Поэтому я вам советую всегда помнить о такой возможности Magento, как виджеты. Спасибо за внимание. Ах да, вот обещанные исходные коды.

Comments are currently closed.