В данной статье мы рассмотрим структуру модуля Magento 2. Посмотрим из чего она состоит, разберем какие бывают конфигурационные файлы и для чего они нужны. В будущем оставлю ссылки на статьи, где каждая упомянутая тут тема будет рассмотрена в деталях.
Базовые файлы для запуска модуля
Модуль может находиться в одном из двух мест относительно корня проекта:
-
в папке app/code/[Vendor Name]/[Module Name]
-
если установлен через composer, то в vendor/[vendor-name]/[module-name]
В процессе разработки модуля его части кладут именно в первую папку.
Также, чтобы модуль работал, в нем должно быть, как минимум, два обязательных файла, и еще один, чтобы модуль можно было ставить через упомянутый выше composer. Лежат они в корне модуля [Vendor]/[Module Name]:
-
registration.php
-
etc/module.xml
-
composer.json
registration.php
Этот файл нужен для того, чтобы зарегистрировать модуль в системе.
Выглядит он следующим образом:
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'VendorName_ModuleName', DIR );
В файле вызывается статический метод register, класса Magento\Framework\Component\ComponentRegistrar, в который передается тип компонента (в нашем случае module), имя вендора и имя модуля через нижнее подчеркивание VendorName_ModuleName, а так же магическая константа __DIR__, которая указывает на директорию, где лежит файл. А так выглядит изнутри сам класс ComponentRegistrar:
<?php namespace Magento\Framework\Component; /** * Provides ability to statically register components. */ class ComponentRegistrar implements ComponentRegistrarInterface { /* * Different types of components */ const MODULE = 'module'; const LIBRARY = 'library'; const THEME = 'theme'; const LANGUAGE = 'language'; const SETUP = 'setup'; private static $paths = [ self::MODULE => [], self::LIBRARY => [], self::LANGUAGE => [], self::THEME => [], self::SETUP => [] ]; /** * Sets the location of a component. */ public static function register($type, $componentName, $path) { self::validateType($type); if (isset(self::$paths[$type][$componentName])) { throw new \LogicException( ucfirst($type) . ' \'' . $componentName . '\' from \'' . $path . '\' ' . 'has been already defined in \'' . self::$paths[$type][$componentName] . '\'.' ); } self::$paths[$type][$componentName] = str_replace('\\', '/', $path); } public function getPaths($type) { self::validateType($type); return self::$paths[$type]; } public function getPath($type, $componentName) { self::validateType($type); return self::$paths[$type][$componentName] ?? null; } /** * Checks if type of component is valid */ private static function validateType($type) { if (!isset(self::$paths[$type])) { throw new \LogicException('\'' . $type . '\' is not a valid component type'); } } }
Как можно увидеть из списка констант, так может регистрироваться не только модуль, но и другие компоненты.
После этого M2 ищет упомянутый выше файл etc/module.xml
etc/module.xml
Выглядит файл следующим образом:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="VendorName_ModuleName" setup_version="1.0.0"> <sequence> <module name="Magento_Customer"/> <module name="Magento_Checkout"/> <module name="Magento_Quote"/> </sequence> </module> </config>
В шапке указывается XSD-схема файла. Если интересно покопаться, то лежит она тут: vendor/magento/framework/Module/etc/module.xsd.
В узле <module> атрибута name отмечается разработчик модуля VendorName и имя модуля ModuleName через нижнее подчеркивание.
В setup_version указывается актуальная версия модуля. Версию важно менять при добавлении нового функционала и при добавлении Install/Upgrade скриптов, которые вносят в базу данных изменения. Если ее не менять, то изменения не будут применены.
Также есть необязательная вложенность с узлом <sequence>, где указывается зависимость вашего модуля от других модулей и то, в какой последовательности они будут загружаться, а также, в какой последовательности будут использоваться plugins, event observers и preferences (об это всем подробнее в будущих статьях). Данный параметр крайне важно указывать, если ваш модуль предполагает кастомизацию функционала других модулей. Т.е. если вы изменяете какой-либо метод класса ProductRepository, то вам в обязательном порядке надо указать зависимость от модуля Magento_Catalog, поскольку этот класс лежит именно там, в противном случае ваши изменения могут быть проигнорированы.
composer.json
Данный файл не является обязательным для того, чтобы модуль стал работать, однако, если вы хотите, чтобы его можно было установить через composer, то файл нужен. Пример:
{ "name": "vendor/module-test", "description": "Magento 2 extension", "require": { "php": ">=7.4", "magento/framework": "*" }, "type": "magento2-module", "version": "1.0.0", "license": [ "GPL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "VendorName\\ModuleName\\": "" } } }
Это вполне себе обычный composer.json файл, который используется повсеместно, а не только в M2. Про его структуру почитать можно здесь.
Вообще, M2 использует стандарт PSR-4, однако для подгрузки модулей из папки app/code также применяется стандарт PSR-0. Это можно заметить в composer.json в корне M2:
Также в секции files можно заметить запись, где упоминается app/etc/NonComposerRegistration.php
Название файла говорит само за себя. Вот как NonComposerRegistration.php выглядит внутри:
<?php declare(strict_types=1); //Register components (via a list of glob patterns) namespace Magento\NonComposerComponentRegistration; use RuntimeException; /** * Include files from a list of glob patterns */ (static function (): void { $globPatterns = require __DIR__ . '/registration_globlist.php'; $baseDir = \dirname(__DIR__, 2) . '/'; foreach ($globPatterns as $globPattern) { // Sorting is disabled intentionally for performance improvement $files = \glob($baseDir . $globPattern, GLOB_NOSORT); if ($files === false) { throw new RuntimeException("glob(): error with '$baseDir$globPattern'"); } \array_map( static function (string $file): void { require_once $file; }, $files ); }})();
Модули можно включать и выключать через консольные команды. Если модуль выключен, то это не значит, что созданные ранее им таблицы в базе данных будут удалены.
Включаем:
php bin/magento module:enable VendorName_ModuleName
Выключаем:
php bin/magento module:disable VendorName_ModuleName
Чтобы данные удалились, нужно использовать другую команду. Однако важно, чтобы в модуле присутствовал класс Setup/Uninstall.php:
php bin/magento module:uninstall VendorName_ModuleName
Структура папок модуля Magento 2
Пройдемся по структуре папок модуля в M2. Папки будут указаны относительно корня модуля.
/Api и /Api/Data
Тут хранятся, так называемые, service contracts, т.е. интейфесы моделей и интерфейсы моделей данных. M2 настоятельно рекомендует их к использованию.
/Block
Папка для блоков и view models. Вью модель — это прослойка между данными и представлением в архитектурном паттерне MVVM. Она нужна для того, чтобы разделить само представление (HTML) и логику, необходимую для подготовки этих данных к дальнейшему их выводу. Подробнее про MVVM можно почитать тут. Как создавать вью модели будет рассмотрено в следующих статьях.
/Console
Содержит в себе код, который вы будете использовать для запуска каких-либо задач через консоль:
php bin/magento [команда]
Для создания своей команды нужно добавить класс, который будет наследовать Symfony\Component\Console\Command\Command
Как видим, без Symfony не обошлось и если вы раньше работали с пакетом symfony/console, то способ создания консольной команды будет вам уже знаком.
В дальнейшем мы подробнее рассмотрим какие cli-скрипты есть у M2 “из коробки” и как создавать свои собственные.
/Controller
Папка для контроллеров, которые отвечают за прием web запросов. По-умолчанию URL запроса состоит из трех сегментов: frontName (берется из файла routes.xml в модуле), название папки, где лежит файл контроллера и название класса контроллера. Как создать свой контроллер и вывести ‘Hello World’ также рассмотрим в дальнейшем.
/Controller/Adminhtml
То же самое, только для админ панели.
/Cron
Все крон-скрипты лежат здесь. Можно также создавать и настраивать свои.
/etc
Папка для конфигурационных файлов в формате xml. Например, module.xml, config.xml и т.д. Также в данной папке могут содержаться поддиректории в зависимости от того, для какой области (далее area)нужно их использовать, например /etc/frontend, /etc/adminhtml, /etc/webapi_soap и т.д. Если подпапка не указана, то конфигурация глобальная, т.е. работает для любой области и наоборот — некоторые файлы должны находиться только в определенной области.
/Helper
Папка для “хелперов”. Поскольку само это понятие считается анти-паттерном, крайне рекомендуется создавать только такие классы “хелперов”, которые можно было бы сделать статическими, или вообще отказаться от их использования.
/i18n
Папка для файлов перевода в формате .CSV, который должен содержать две колонки: оригинальная фраза и перевод. Имя файла указывается в виде локали, на какой язык будем переводить. Например: en_US.csv
i18n, если кто не знал, расшифровывается как internationalization
/Model
Здесь хранятся модели, а именно, классы для работы с данными и бизнес-логика.
/Model/ResourceModel
Классы взаимодействия с БД. Прямые запросы к ней хранятся именно здесь.
/Observer
Папка для event listeners. Класс event listenerа должен наследовать интерфейс \Magento\Framework\Event\ObserverInterface и реализовавать метод execute(). Вся логика должна быть вынесена в отдельный класс, а сам класс должен подключаться в listener через инъекцию зависимостей. При таком подходе бизнес логику можно легко тестировать, а код будет оставаться чистым.
/Plugin
Папка для плагинов. Плагины нужны для изменения поведения публичных методов. Можно полностью менять повередние метода, либо производить какие-то дополнительные действия с данными. Подробнее рассмотрим в отдельной статье.
/Setup
Здесь находятся файлы установки и обновления БД.
-
InstallSchema.php (для создания схемы БД)
-
UpgradeSchema.php (для обновления схемы БД)
-
InstallData.php (для добавления данных в БД)
-
UpgradeData.php (для обновления данных в БД)
-
Recurring.php (вызывается после каждого обновления схемы БД)
-
RecurringData.php (вызывается после каждого обновления данных БД)
-
Uninstall.php (используется для удаления данных из БД при удалении модуля)
Кстати, с версии 2.3 появилась возможность делать изменения в БД при помощи XML файлов. Вот статья в документации.
/Test
Папка для разных видов тестов: юнит-тестов, интеграционных и т.д
/Ui
Папка для классов, которые наполняют Ui-компоненты данными (data providers).
Ui-компоненты — это стандартизированные элементы пользовательского интерфейса, которые нужны для повторного применения в целях отрисовки форм, таблиц, окон и т.д. Для вывода используется JavaScript и HTML, конфигурация происходит с помощью xml, а данные готовятся при помощи Data Providers и приходят с сервера.
Довольно сложная и обширная тема, которая будет рассмотрена в следующих статьях.
/view/[area]/layout
В данной папке хранятся файлы в формате .xml, которые отвечают за связь шаблонов и блоков, т.е. представления и вью модели.
/view/[area]/templates
HTML шаблоны в формате .phtml, а именно, представление. Отвечает за вывод данных на frontend.
/view/adminhtml/ui_component
Файлы конфигурации Ui-компонентов в формате xml, которые используются для вывода Ui-элементов в админке. Например: формы, сетки (grid).
/view/[area]/web
Папка для JavaScript, CSS, Less, Sass файлов.
/view/[area]/web/template
Папка шаблонов в формате html. используется для JavaScript и Knockout JS. Knockout — это JS-библиотека на подобие ReactJs или Vue, только постарше и похуже. Подронее про него тут
Конфигурационные файлы модуля Magento 2
Рассмотрим базовые файлы конфигурации модуля. Пока что без подробностей, а просто перечислим и обозначим основную функцию. Все подробности будут разобраны в последующих статьях.
/etc/adminhtml/system.xml
Определяет tabs, sections, groups, fields в админке в разделе Store>Configuration. Иными словами, с помощью него создаются варианты настроек в админ-панели.
/etc/acl.xml
В данном файле описываются правила для ограничения прав доступа пользователей, которые будет использовать админку или API.
/etc/config.xml
Настройки админки Store->Configuration по-умолчанию. Используются до того момента, пока пользователь не внес свои изменения. Сохраненные настройки хранятся в БД в таблице core_config_data.
/etc/crontab.xml
Здесь определяются задачи планировщика (cron jobs). При настройке M2 не нужно выносить в crontab каждую задачу на уровне системы, а лишь одну — родительскую. Запускаться она должна каждую минуту.
* * * * * /usr/bin/php /var/www/html/magento2/bin/magento cron:run
Все остальные задачи настраиваются, планируются и выполняются самим приложением.
/etc/[area]/di.xml
Пожалуй, наиболее часто используемый файл при работе с модулями — настройка инъекции зависимостей. Здесь переопределяются классы (preference), определяются service contracts, плагины (plugins), виртуальные типы (virtual types), передаются аргументы в конструкторы объектов.
/etc/email_templates.xml
Тут определяются шаблоны писем для email-рассылок.
/etc/[area]/events.xml
Файл для определения слушателей событий (event listener). В то время как плагинам разрешено менять результат выполнения какого-либо метода, у событий и их слушателей другие цели, а именно, выполнять какое-то действие до или после отработки какого-либо функционала. Например, отправить пользователю письмо после размещения заказа. Подробнее в следующих статьях.
/etc/indexer.xml
Определяет индексеры. Вся информация о продукте или категории содержится в разных таблицах в БД и, чтобы собрать всю эту информацию, mysql-запрос может долго выполняться и\или требовать много ресурсов. Для того, чтобы информация доставалась быстрее, существуют индексеры. Они собирают все необходимые данные и записывают ее в специальные таблицы в БД, откуда они и берутся при запросе от клиента. Можно создавать и свои собственные индексеры, а также посмотреть их статус в админке System>Index Management
/etc/adminhtml/menu.xml
Содержит настройки меню админки: табы, пункты меню и прочее.
/etc/mview.xml
Вызывает тип event, когда были изменены данные в определенной колонки в БД. Часто используется для индексации.
/etc/[area]/routes.xml
Когда происходит запрос к серверу, определяет первый элемент пути к layout файлу. Содержит routeId и frontName — используется в качестве первого элемента пути в URL.
Например: http://localhost/sales/order/history, где sales — frontName, order — папка контроллера, history — имя контроллера.
/etc/view.xml
То же самое, что и config.xml, только для тем, т.е. настройки темы по-умолчанию.
/etc/webapi.xml
Определяет доступные методы, классы API для доступа к M2 из вне.
/etc/widget.xml
Файл для определения виджетов — маленьких статических или динамических блоков с данными, которые можно встраивать на страницы веб-сайта.
/etc/extension_attributes.xml
Конфигурационный файл для добавления дополнительных атрибутов к определенной сущности (напр. к сущности продукта, заказа, квоте).
Это был не весь список, но базовые файлы я перечислил. С полным списком файлов можно ознакомиться здесь. Также каждый файл из перечисленных выше является частью отдельной темы. Каждая из этих тем будет рассмотрена в дальнейших статьях.
ссылка на оригинал статьи https://habr.com/ru/post/674316/
Добавить комментарий