Как создать тему для Magento 2 с нуля



    Здравствуйте, уважаемые хабрапользователи! В этой публикации хочу описать процесс создания темы для Magento 2 с нуля. Magento 2 имеет достаточно большое количество нововведений и улучшений по сравнению с первой версией. По большей части они относятся к клиентской части.

    Вот некоторые из них:

    1. Полная поддержка HTML5 и CSS3;
    2. Встроенный препроцессор LESS;
    3. Асинхронная загрузка модулей с помощью RequireJS (без ручного добавления скриптов в cекцию head);
    4. jQuery/jQuery UI вместо библиотеки Prototype;
    5. Magento UI библиотека (набор компонентов для простого и гибкого рендеринга пользовательского интерфейса).

    Самое интересное – под катом!

    Касательно разработки тем, в Magento 2 была введена новая модульная структура кода. Теперь все статические сss, js, а также файлы изображений размещаются в папке web темы, а папка skin была удалена с корневого каталога Magento. Кроме этого, была введена папка view в модулях, которая хранит шаблоны и файлы, которые относятся к уровню представления MVC конкретно для каждого модуля.

    Следует создать новую тему и более детально рассмотреть структуру директорий и файлов. Поехали!

    Создание директории темы


    Темы в Magento 2 находятся в каталоге (M2_root)/app/design/frontend. Сначала необходимо создать папку Vendor (называлась Package в Magento 1) и уже в ней создать папку для темы.

    Например: (M2_root)/app/design/frontend/Singree/walkbeyond. Где Singree – vendor, а walkbeyond – код темы. В коде можно использовать любые комбинации из букв и цифр.

    После создания этих директорий тему необходимо объявить, чтобы ее можно было сделать активной в административной части.

    Объявление и регистрация


    Чтобы Magento 2 смогла увидеть созданную тему, необходимо создать файл: (M2_root)/app/design/frontend/(vendor)/(theme codename)/theme.xml с таким содержанием:

    <theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    
    <title>walkbeyond</title>
    <parent>Magento/blank</parent>
    <media>
    <preview_image>media/walkbeyond.jpg</preview_image>
    </media>
    </theme>
    

    В теге title указывается название темы. В parent указывается тема, которая устанавливается как родительская (все ненайденные статические файлы/файлы шаблонов будут браться с родительской темы). В примере указывается blank, которая поставляется вместе с M2. Она является базовой и своей родительской не имеет. Тем не менее, уровней наследования в Magento 2 может быть сколько угодно, и здесь нет никаких ограничений в отличие от первой версии.



    В теге preview_image указывается миниатюра для представления темы в администраторской части.

    Для регистрации темы в системе необходимо создать файл registration.php в корне:

    <?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::THEME,
        'frontend/Singree/walkbeyond',
        __DIR__
    );
    

    Необязательно, но можно создать файл composer.json для распространения темы как пакета composer. Пример файла:

    {
        "name": "Singree/walkbeyond",
        "description": "N/A",
        "require": {
            "php": "~5.5.0|~5.6.0|~7.0.0",
            "magento/theme-frontend-blank": "100.0.*",
            "magento/framework": "100.0.*"
        },
        "type": "magento2-theme",
        "version": "100.0.1",
        "license": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "autoload": {
            "files": [
                "registration.php"
            ]
        }
    }
    

    Создание директорий для статических файлов


    Для хранения стилей, javascript скриптов, изображений и шрифтов необходимо создать папку web в корневом каталоге темы. Структура папок следующая:

    app/design/frontend/Singree/walkbeyond/
    ├── web/
    │ ├── css/
    │ │ ├── source/ 
    │ ├── fonts/
    │ ├── images/
    │ ├── js/
    

    Отметим, что все эти папки являются необязательными.

    В папке images находятся все статические файлы темы, сюда же можно добавить logo.svg (имя по умолчанию) для переопределения логотипа темы. В папке сss/source, согласно родительской теме blank, можно создать _theme.less файл c переопределением базовых переменных Magento UI. В папке (M2_root)/lib/web/css/source/lib/variables/ в исходных файлах можно найти значения по умолчанию для тех переменных, которые можно переопределить. В сss/source можно задавать стили для модулей в файле _module.less и для виджетов в файле _widgets.less. Для небольших правок можно создавать файл _extend.less.

    Конфигурация изображений


    Обязательным для темы является файл etc/view.xml (если он не определен в родительской теме), который содержит значения свойств для изображений товаров, таких как высота, ширина, прозрачность, цвет фона и т.п. Этот файл необходимо полностью скопировать с базовой темы (значения не наследуются) Свойства изображений задаются по атрибутам идентификатора и типа в рамках элемента:

    <images module="Magento_Catalog">
    ...
    <images/>
    

    Для примера можно изменить размер изображения в табличном представлении товаров каталога.



    Файл etc/view.xml:

    <?xml version="1.0"?>
    <view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd">
        <media>
            <images module="Magento_Catalog">
                <image id="category_page_grid" type="small_image">
                    <width>200</width>
                    <height>200</height>
                </image>
                ...
        </media>
    ...
    </view>
    

    Идентификатор category_page_grid – уникальный в рамках темы. Тип small_image соответствует Small Image Role в администраторской части. Допустимые значения типов изображений: image, small_image, swatch_image, swatch_thumb и thumbnail.



    После сохранения товара, все изображения являются закешированными. После изменения размеров можно выполнить команду php (M2_root)/bin/magento catalog:images:resize для регенерации картинок.

    В результате была получена такая структура:



    Применение темы в административной части


    Тему можно активировать в настройках магазина после создания в файловой системе. Для этого переходим в раздел Content — Design — Themes и проверяем, что созданная тема присутствует в списке:



    Если мы видим созданную тему в списке, переходим в Content → Design → Configuration и там нажимаем edit для определенного вебсайта или выбранного магазина:



    Выбираем тему (Applied Theme) и нажимаем Save configuration:



    Если у вас включен кеш, необходимо очистить его после применения темы. Для этого перейдем в раздел System — Cache Management и обновляем все невалидные типы кеша:



    В результате, мы получим все ту же тему magento/blank, но с другим логотипом и размером картинок:



    Использование LESS для изменения стилей


    После создания темы можно приступить к изменению внешнего вида страниц. Чтобы отредактировать стили проекта, необходимо использовать один из нескольких типов препроцессинга LESS в Magento 2:

    • Серверная компиляция LESS;
    • Клиентская компиляция LESS c помощью less.js.

    Клиентская компиляция чаще используется в режиме разработки, так как все изменения будут видны сразу: браузер будет выполнять компиляцию каждый раз при обращении к файлам стилей. При серверной компиляции необходимо вручную каждый раз удалять содержимое папок pub/static и var/view_preprocessed. Эти действия можно оптимизировать с помощью таскраннера Grunt. Он будет отслеживать изменения в файлах, очищать указанные папки и компилировать less автоматически.

    Изменить тип компиляции можно в админ части по пути: Stores → Configuration → Advanced → Developer → Front-end development workflow → Workflow:



    В нашем простом примере будет использоваться серверная компиляция, которая установлена по умолчанию. Установим цвет фона сайта, а также шрифт в созданном _theme.less файле:

    @page__background-color: #484848;
    @text__color: #fff;
    @font-family__base: 'Arial', sans-serif;
    

    После удаления содержимого директорий /pub/static/frontend/Singree/walkbeyond/en_US и var/view_preprocessed, мы можем увидеть изменение внешнего вида сайта:



    Magento 2: использование макетов в теме




    В Magento 2 в определенной теме можно как расширять, так и переопределять макеты. Чтобы полностью не копировать страничные или общие макеты с базовой темы, необходимо указать только макет расширения в папке темы по таким путям:

    <theme_dir>
     |__/<Namespace>_<Module>
       |__/layout
         |--<layout1>.xml
         |--<layout2>.xml
    

    Например, чтобы расширить макет catalog_category_view модуля Catalog, который находится по пути (сatalog_module_dir)/view/frontend/layout/catalog_category_view.xml, необходимо создать файл по пути: (theme_dir)/Magento_Catalog/layout/catalog_category_view.xml

    Удалить какой-либо блок (например, описание категории) можно так:

    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
        <body>
            <referenceBlock name="category.description" remove="true"/>
        </body>
    </page>
    

    Не все задачи кастомизации можно выполнить расширением макета. Если количество изменений крайне велико, лучше переопределить макет. То есть этот новый файл будет использован вместо файла с родительской темы (или основного макета).

    Примеры кастомизации макетов, которые подразумевают переопределение макета:

    • Вызов метода, который подавляет другой метод родительского макета (Если есть метод, который отменяет действие определенно метода родительского макета, то можно его вызвать и не переопределять весь макет);
    • Изменение количества аргументов метода;
    • Отмена удаления блока/контейнера, используя remove атрибут;
    • Установка XML атрибутов блоков/контейнеров (некоторые атрибуты, такие как htmlClass, htmlId, label могут быть изменены в расширяющих макетах);
    • Удаление аргументов блоков;
    • Удаление всех дескрипторов путем переопределения макетного файла с пустым дескриптором;
    • Модифицирование включения дескрипторов.

    Можно переопределить основные базовые макеты путем создания папки override/base в папке модуля темы:

    <theme_dir>
      |__/<Namespace_Module>
        |__/layout
          |__/override
             |__/base
               |--<layout1>.xml
               |--<layout2>.xml
    

    Эти файлы будут переопределять макеты:

    <module_dir>/view/frontend/layout/<layout1>.xml
    

    <module_dir>/view/frontend/layout/<layout2>.xml
    

    Также можно переопределить макеты родительской темы, создав папку override/theme в папке модуля темы:

    <theme_dir>
      |__/<Namespace_Module>
        |__/layout
          |__/override
             |__/theme
                |__/<Parent_Vendor>
                   |__/<parent_theme>
                      |--<layout1>.xml
                      |--<layout2>.xml
    

    Эти файлы будут переопределять макеты, которые находятся по таким путям:

    <parent_theme_dir>/<Namespace>_<Module>/layout/<layout1>.xml
    <parent_theme_dir>/<Namespace>_<Module>/layout/<layout2>.xml
    

    Шаблоны темы


    В темах Magento 2 возможно полностью переопределять шаблоны модулей, как и в случае с макетами. Для переопределения шаблонов модуля (module_dir)/view/frontend/templates/(path_to_templates), необходимо создать папку templates в папке модуля темы (theme_dir)/(Namespace)_(Module)/templates/(path_to_templates).

    Например, можно в файле мини-корзины Singree/walkbeyond/Magento_Checkout/templates/cart/minicart.html добавить текстовое сообщение для вывода «Количество товаров»:

    
    <div data-block="minicart" class="minicart-wrapper">
        <a class="action showcart" href="<?php /* @escapeNotVerified */ echo $block->getShoppingCartUrl(); ?>"
           data-bind="scope: 'minicart_content'">
            <span class="cart-title hidden-xs"><?php /* @escapeNotVerified */ echo __('Shopping cart'); ?></span>
            <span class="counter total-qty empty"
                  data-bind="css: { empty: cart().summary_count == 0 }, blockLoader: isLoading">
            <?php /* @escapeNotVerified */ echo __('Products count:'); ?>    <span class="counter-number"><!-- ko text: cart().summary_count --><!-- /ko --></span>
                <span class="counter-label">
                <!-- ko if: cart().summary_count -->
                    <!-- ko text: cart().summary_count --><!-- /ko -->
                    <!-- ko i18n: 'items' --><!-- /ko -->
                <!-- /ko -->
                </span>
            </span>
        </a>
        <?php if ($block->getIsNeedToDisplaySideBar()): ?>
            <div class="block block-minicart empty"
                 data-role="dropdownDialog"
                 data-mage-init='{"dropdownDialog":{
                    "appendTo":"[data-block=minicart]",                "triggerTarget":".showcart",
                    "timeout": "2000",                "closeOnMouseLeave": false,
                    "closeOnEscape": true,                "triggerClass":"active",
                    "parentClass":"active",        "buttons":[]}}'>
                <div id="minicart-content-wrapper" data-bind="scope: 'minicart_content'">
                    <!-- ko template: getTemplate() --><!-- /ko -->
                </div>
            </div>
        <?php endif ?>
        <script>
            window.checkout = <?php /* @escapeNotVerified */ echo \Zend_Json::encode($block->getConfig()); ?>;
        </script>
        <script type="text/x-magento-init">
        {
            "[data-block='minicart']": {
                "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
            },
            "*": {
                "Magento_Ui/js/block-loader": "<?php /* @escapeNotVerified */ echo $block->getViewFileUrl('images/loader-1.gif'); ?>"
            }
        }
        </script>
    </div>
    

    Локализация темы


    Перевод темы осуществляется с помощью словарей перевода. Словари с переводами ищутся в таких локациях:

    • <parent_theme_dir>/i18n/ (идет просмотр во всех родительских темах)
    • <current_theme_dir>/i18n/

    Папка i18n может находиться в каждом модуле или глобально в папке app. Словари с папками темы имеют более высокий приоритет в поиске переведенной строки.

    Чтобы сгенерировать файл с переводами в папке темы можно использовать i18n tool.

    Можно запустить такую команду в корневом каталоге magento 2:

    
    php bin/magento i18n:collect-phrases --output="app/design/frontend/Singree/walkbeyond/i18n/en_US.csv" app/design/frontend/Singree/walkbeyond
    

    Она соберет все строки в словарь. Далее файл словаря: app/design/frontend/Singree/walkbeyond/i18n/en_US.csv. Его можно открыть любым редактором таблиц и изменить перевод любых строк в правой колонке. Переведённые строки, вместо основных, можно будет увидеть после применения темы.

    Удаление темы


    Если тема является Composer пакетом, ее можно удалить командой (с корневого каталога):

    
    php bin/magento theme:uninstall [-c|--clear-static-content] {theme path} ... {theme path}
    

    {theme path} – относительный путь к теме, начиная с имя area (frontend). В нашем случае: frontend/Singree/walkbeyond.

    --clear-static-content – удаляет статические файлы (для которых не нужна автоматическая генерация: css, js, images).

    В случае, если тема не является Сomposer пакетом, для ее удаления необходимо выполнить такие шаги:

    • Удалить папку темы app/design/frontend/(Vendor);
    • Удалить содержимое var/view_preprocessed;
    • Удалить содержимое of pub/static/frontend/;
    • Открыть базу данных мадженто 2, найти theme таблицу и удалить строку с названием темы;
    • Удалить кеш командой php bin/magento cache:flush.

    Вывод


    В статье были рассмотрены основные составляющие части темы: как создать с нуля структуру директорий и файлов темы, картинку предпросмотра. Также был рассмотрен процесс переопределения стилей, макетов и шаблонов темы: был переведен сайт с помощью словарей перевода. Далее следует рассмотреть таблицу составляющих темы:



    Большая часть данной структуры была затронута в нашей статье. Также стоило бы упомянуть о правилах работы с клиентскими библиотеками Javascript (например, require.js) или детальнее описать работу с блоками и контейнерами макетов, но тогда размер статьи слишком увеличился бы и читать ее стало бы совершенно неудобно.

    Благодарю всех за внимание!
    • +8
    • 21,1k
    • 1
    Поделиться публикацией
    Комментарии 1
      0
      Спасибо за статью, с нетерпением жду еще инфы по маженто2.
      Исправьте пожалуйста тег статьи с [magneto2] на [magento 2] как во всех предыдущих.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое