С появлением Magento 2 многие вопросы требуют объяснения. Сегодня очередь дошла до разбора процесса генерации кода в системе, как одной из новых ключевых концепций в Magento 2. Вас когда-либо волновал вопрос, когда и почему создается код в папке var/generation
и какой процесс за это отвечает? Если это так, тогда эта статья для вас.
Генерация кода может быть вызвана двумя способами:
Для второго способа вам нужно запускать команду:
magento setup:di:compile
чтобы создать необходимые файлы. Оба варианта ведут к созданию классов в папке var/generation
.
Какие классы генерируются?
Существует несколько типов классов, которые генерируются системой. Мы остановимся на 3-х самых важных:
А теперь давайте по порядку.
Фабричные классы используются для создания объектов, которые не могут быть вставлены автоматически. Например, объект товара должен быть загружен из базы данных, но для контейнера инъекции зависимостей недостаточно информации для создания этого объекта. Вот почему используются фабрики.
Давайте посмотрим на существующий класс в app/code/Magento/Catalog/Model/Product/Copier.php
/** * @param CopyConstructorInterface $copyConstructor * @param \Magento\Catalog\Model\ProductFactory $productFactory */public function __construct( CopyConstructorInterface $copyConstructor, \Magento\Catalog\Model\ProductFactory $productFactory ) { $this->productFactory = $productFactory; $this->copyConstructor = $copyConstructor; }
Пояснение рабочего процесса:
$productFactory
)create()
(единственному методу на фабричном объекте) для создания как можно большего количества экземпляров Product
.
Вот как вы, как разработчик, можете использовать фабрики. В фоновом режиме система сгенерирует файл, расположенный в /var/generation/Magento/Catalog/Model/ProductFactory.php
, который выглядит так (упрощенно):
<?php namespace Magento\Catalog\Model; class ProductFactory { public function __construct( \Magento\Framework\ObjectManagerInterface $objectManager, $instanceName = '\\Magento\\Catalog\\Model\\Product' ) { $this->_objectManager = $objectManager; $this->_instanceName = $instanceName; } public function create(array $data = array()) { return $this->_objectManager->create($this->_instanceName, $data); } }
Как мы видим, единственной целью фабричных классов является делегирование инстанциирования объектов объектным менеджерам.
Magento 2 использует конструктор инъекций, в котором указываются все требуемые зависимости. Вы не можете создавать объекты без объявления всех зависимостей. Что делать, если вы хотите иметь дополнительные зависимости? Для этого существуют прокси.
<config> <type name="Magento\Catalog\Model\Resource\Product\Collection"> <arguments> <argument name="customerSession" xsi:type="object"> Magento\Customer\Model\Session\Proxy </argument> </arguments> </type> </config>
Пояснение рабочего процесса:
di.xml
Proxy
, добавленное в Magento\Customer\Model\Session\
. Зависимости, отмеченные таким образом, являются необязательными зависимостями.
В фоновом режиме система сгенерирует файл, расположенный в /var/generation/Magento/Customer/Model/Session/Proxy.php
, который выглядит так (упрощенно):
<?php namespace Magento\Customer\Model\Session; class Proxy extends \Magento\Customer\Model\Session { protected function _getSubject() { if (!$this->_subject) { $this->_subject = true === $this->_isShared ? $this->_objectManager->get($this->_instanceName) : $this->_objectManager->create($this->_instanceName); } return $this->_subject; } ... }
Как мы видим, это расширяет исходный класс и переопределяет каждый метод, который делегирует вызов к исходному образцу. Это означает, что при первом вызове прокси метода исходный экземпляр создается со всеми его зависимостями. Поэтому единственной целью прокси является отсрочка создания экземпляра (и его зависимостей) до самого первого использования.
Проще говоря, плагины являются основными механизмами кастомизации Magento 2. Больше не нужно перезаписывать класс. Плагин позволяет вам подключаться и делать что-то до, после или вокруг любого public
метода приложения.
Давайте посмотрим на системный плагин:
<?php namespace Magento\Store\App\Action\Plugin; class StoreCheck { public function aroundDispatch( \Magento\Framework\App\Action\Action $subject, \Closure $proceed, \Magento\Framework\App\RequestInterface $request ) { if (!$this->_storeManager->getStore()->getIsActive()) { throw new \Magento\Framework\Exception\State\InitException( __('Current store is not active.') ); } return $proceed($request); } }
Пояснение рабочего процесса:
di.xml
, например, так:
<config> <type name="Magento\Framework\App\Action\Action"> <plugin name="storeCheck" type="Magento\Store\App\Action\Plugin\StoreCheck" sortOrder="10"/> </type> </config>
В результате система сгенерирует класс Interceptor
в /var/generation/Magento/Framework/App/Action/Interceptor.php
<?php namespace Magento\Framework\App\Action\Action; class Interceptor extends \Magento\Framework\App\Action\Action { public function dispatch(\Magento\Framework\App\RequestInterface $request) { $pluginInfo = $this->pluginList->getNext('\\Magento\\Framework\\App\\Action\\Action', 'dispatch'); if(!$pluginInfo) { return parent::dispatch($request); } else { return $this->__callPlugins('dispatch', func_get_args(), $pluginInfo); } } }
В отличие от прокси, на этот раз инструмент генерации будет генерировать только те методы, которые вы хотите переписать.
Вот и все на сегодня. Пишите свои комментарии в форме комментирования ниже.
Довольно часто у программистов возникает соблазн написать какую-нибудь обширную функцию, которая должна решать определенную задачу.…
Дискуссии вокруг этой темы вас, вероятно, уже утомили. Но я в данной статье постараюсь показать…
Консоль браузера (также известная как консоль JavaScript или веб-консоль) — это мощный инструмент для разработчиков,…
Никогда не указывайте на ошибки, если не знаете, как их исправить Джордж Бернард Шоу
Когда необходимо сделать выбор, а вы его не делаете, — это тоже выбор Уильям Джеймс…
Когда вы ставите перед собой цели, очень важно быть максимально конкретным. Здесь не поможет простая…