Підступна війна росії проти України. Орієнтовні втрати ворога
(станом на 29.04.2024)
467470
осіб
348
літаків
325
гелікоптерів
7285
танків
14007
ББМ
11985
артилерія
778
ППО
1051
РСЗВ
16109
машин
26
кораблі і катери
Короткий огляд генерації коду в Magento 2
Опубліковано

Короткий огляд генерації коду в Magento 2

З появою 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>

 

 

Пояснення робочого процесу:

  • Розробник ніколи не чіпає PHP файли для використання проксі, він використовує тільки файл 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);
  }
 }
}

 

 

На відміну від проксі, на цей раз інструмент генерації буде генерувати тільки ті методи, які ви хочете переписати.

 

 

Ось і все на сьогодні. Пишіть свої коментарі в формі коментування нижче.

 

 

Напишіть тут свою думку/питання

Ваша пошта не публікуватиметься. Обов’язкові поля позначені *