Що ж, давай почнемо 😎
Вступ
На продакшен оточенні, Magento повинна працювати на файловій системі налаштованої лише для читання, це рекомендується з погляду безпеки.
На запис доступні лише такі каталоги:
- app/etc
- pub/static
- pub/media
- var
Важливе зауваження: папка зі згенерованими класами була переміщена з var/generation у generated/code. Зараз, ця папка не доступна для запису в продакшені. Ці папки мають аналогічні дозволи на запис у хмарній інфраструктурі Magento.
Отже, якщо ти додаси неправильно залежність, то Magento може поламатися.
Клас у точці доступу
Розробник пише клас у точці доступу і додає в конструктор залежність на фабрику, що генерується.
<?php
use YourVendor\SomeModule\Model\GeneratedFactory;
require realpath(__DIR__) . '/../app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
class SomeClass
{
private $generatedFactory;
public function __construct(GeneratedFactory $generatedFactory)
{
$this->generatedFactory = $generatedFactory;
}
// Some code here...
}
$someObject = $bootstrap->getObjectManager()->create(SomeClass::class);
// There is some code that uses $someObject
Цей приклад буде працювати в режимі розробника, GeneratedFactory генеруватиметься на льоту. Але в режимі продакшен, на файловій системі тільки для читання, ти зіткнешся з помилкою, що GeneratedFactory не може бути збережена в каталозі generateted/code.
Це відбувається тому, що Magento не сканує точку входу під час роботи команди bin/magento setup:di:compile. І якщо точка входу містить визначення класів, що генеруються, то вони будуть проігноровані.
Є два шляхи, як це виправити.
Як це виправити?
Перший шлях - це створити реальний клас фабрики у файловій системі.
Другий шлях - це перемістити клас SomeClass у папку app/code/YourVendor/SomeModule. Тоді сканер коду Magento знайде в класі SomeClass залежність на фабрику, що генерується GeneratedFactory, і генератор коду згенерує цю фабрику.
Приклад класу SomeClass:
<?php
namespace YourVendor\SomeModule;
use YourVendor\SomeModule\Model\GeneratedFactory;
class SomeClass
{
private $generatedFactory;
public function __construct(GeneratedFactory $generatedFactory)
{
$this->generatedFactory = $generatedFactory;
}
// Some code here...
}
Редагуємо точку входу my_api/index.php
<?php
use YourVendor\SomeModule\SomeClass;
require realpath(__DIR__) . '/../app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$someObject = $bootstrap->getObjectManager()->create(SomeClass::class);
// There is some code that uses $someObject
Неправильне додавання залежності
Неправильне додавання залежності в існуючий клас на клас, що генерується. Наприклад, наступний код буде коректно працювати в режимі розробника, але завершиться невдачею в режимі продакшен на файловій системі тільки для читання.
<?php
namespace YourVendor\SomeModule;
use YourVendor\SomeModule\Model\GeneratedFactory;
use Magento\Framework\App\ObjectManager;
class SomeClass
{
private $generatedFactory;
private $someParam;
public function __construct($someParam)
{
$this->someParam = $someParam;
$this->generatedFactory = ObjectManager::getInstance()->get(GeneratedFactory::class);
}
// Some code here...
}
Як це виправити?
Подібний підхід іноді використовується для додавання залежностей та збереження зворотної сумісності. Але цей підхід має ту саму проблему, що й приклад вищий. Під час роботи команди bin/magento setup:di:compile, клас, що генерується, не буде згенерований.
Тут також є два способи, як це виправити.
Перший шлях - це створити реальний клас фабрики у файловій системі.
Другий шлях - це трохи змінити конструктор SomeClass
Приклад класу SomeClass:
<?php
namespace YourVendor\SomeModule;
use YourVendor\SomeModule\Model\GeneratedFactory;
use Magento\Framework\App\ObjectManager;
class SomeClass
{
private $generatedFactory;
private $someParam;
public function __construct($someParam, GeneratedFactory $generatedFactory = null)
{
$this->someParam = $someParam;
$this->generatedFactory = $generatedFactory ?: ObjectManager::getInstance()->get(GeneratedFactory::class);
}
// Some code here...
}
В цьому випадку:
- ми додали нову залежність
- ми зберегли зворотну сумісність
- генерований клас буде згенерований
- Magento коректно працює в режимі продакшен на файловій системі тільки для читання.
Якщо у тебе є якісь питання чи коментарі - пиши, з радістю відповім 😉
Ти можеш знайти приклад неправильного DI в модулі Magento в цьому репозиторії: https://github.com/BaDos/example-wrong-di