- PVSM.RU - https://www.pvsm.ru -
Процесс создания объектов [1] в Magento 2 включает в себя некоторые особенности, присущие именно Magento 2 и связанные с автоматической генерацией кода при определенных условиях (proxies [2], factories [3] и interceptors [4]). С interceptor'ами для меня было все более-менее понятно, а вот назначение двух других типов генерируемых классов было скрыто туманом непонимания. И если относительно фабрик у меня туман пока еще остается, то вот относительно прокси-классов — туман развеялся.
Предположим, что мы делаем команду [5] для выполнения каких-либо действий в режиме CLI. Предположим, что мы используем в этой команде имплементацию интерфейса MagentoQuoteApiCartManagementInterface, которую нам передает в конструктор ObjectManager:
public function __construct(MagentoQuoteApiCartManagementInterface $cartManagement) {}
Мы можем не использовать имплементацию MagentoQuoteApiCartManagementInterface напрямую в нашей команде, эта имплементация может подтягиваться косвенно — наша команда зависит от ClassA, который зависит от ClassB, который зависит от ..., который зависит от MagentoQuoteApiCartManagementInterface.
Тем не менее, если в нашей команде есть прямая или косвенная зависимость от default'ой имплементации интерфейса MagentoQuoteApiCartManagementInterface, то при попытке запустить команду, например:
$ ./bin/magento list
мы вывалимся по ошибке
[MagentoFrameworkExceptionSessionException]
Area code not set: Area code must be set before starting a session.
Это происходит потому, что перед началом работы ./bin/magento создает все команды, которые прописаны в etc/di.xml дескрипторах. Для создания нашей команды ObjectManager создает для нее класс MagentoQuoteModelQuoteManagement, имплементирующий интерфейс MagentoQuoteApiCartManagementInterface. В процессе создания зависимостей для этого класса ObjectManager доходит до создания зависимости MagentoFrameworkSessionSessionManager в конструкторе которого есть строка:
$this->start();
и если по каким-то причинам (например, Area code not set) сессия не стартует, то выбрасывается исключение и выполнение CLI-команды аварийно завершается. И совершенно не важно, что мы не собирались использовать сессии при выполнении нашей команды (или не подозревали о том, что создание чего-то там, имплементирующего нужный нам интерфейс, вылетит по причине того, что для создания этого "чего-то там" нужен ресурс, который в данном режиме непроинициирован).
Разработчики Magento 2, столкнувшись с таким некошерным поведением объектов в процессе их создания ObjectManager'ом пришли к простому решению — прокси-классы. Достаточно указать в конструкторе зависимость не от MagentoQuoteApiCartManagementInterface, а от MagentoQuoteApiCartManagementInterfaceProxy, и при создании вашего объекта в него будет передаваться не непосредственная имплементация интерфейса, а класс-декоратор (генерируется автоматически), который и создаст непосредственную имплементацию при первом же использовании какого-либо имплементируемого метода.
Другими словами, достаточно дописать после имени интерфейса или класса Proxy:
public function __construct(MagentoQuoteApiCartManagementInterfaceProxy $cartManagement) {}
как проблема с запуском команды решается (если не решается — почистите нагенеренное: rm -fr ./var/cache/* ./var/generation/*). ClassAProxy, ClassBProxy,…, MagentoQuoteApiCartManagementInterfaceProxy — выбирай уровень по душе.
У Алана Сторма есть хорошая статья "Magento 2 Object Manager: Proxy Objects [6]" (у него вообще, много хороших статей по Magento 2), но из нее мне не совсем было понятно, для чего именно создавались Proxy-декораторы в Magento 2 и какова сфера их применения. Только после того, как я столкнулся с невозможностью перевести свое приложение в production mode
$ ./bin/magento deploy:mode:set production
из-за предательского поведения некоторых конструкторов, я несколько прояснил для себя сферу применения прокси-классов в Magento 2.
Автор: flancer
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/proxy/218621
Ссылки в тексте:
[1] создания объектов: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/depend-inj.html
[2] proxies: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/proxies.html
[3] factories: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/factories
[4] interceptors: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html
[5] команду: https://github.com/flancer32/sample_mage2_module/blob/Habr_Di_Proxy/src/Console/Command/Own.php#L17
[6] Magento 2 Object Manager: Proxy Objects: http://alanstorm.com/magento_2_object_manager_proxy_objects/
[7] Источник: https://habrahabr.ru/post/317162/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.