Как нельзя добавлять зависимости на генерируемые классы в Magento

Часто разработчики модулей для Magento допускают ошибки при добавлении зависимостей, из-за которых при определенных условиях может перестать работать часть функционала или вся система. И вот почему...


После перевода Magento в production мод вся файловая система должна быть readonly (только для чтения). Исключение составляют следующие директории: var, pub/static и pub/media. Это официальная рекомендация Magento.

Эти же правила действуют на Magento Cloud.
Но я часто сталкиваюсь с проблемами генерируемых фабрик или прокси в модулях сторонних разработчиков. Обычно проблема в том, что классы пытаются генерироваться на лету когда файловая система уже readonly.

Ниже два примера, как не нужно делать и рекомендация как делать нужно, чтоб ничего не фейлилось :)

Пример первый

Разработчиком написан класс в точке входа my_api/index.php, который принимал аргументом конструктора генерируемую фабрику:

В developer моде все будет работать как задумывалось и проблем не возникнет. GeneratedFactory будет сгенерирована на лету. Но в production моде мы получим ошибку о том, что невозможно записать сгенерируемую фабрику.

Это просиходит потому что bin/magento setup:di:compile не сканирует точки входа на предмет определения в них генерируемых фабрик, прокси и т.д. То есть, будут сгенерированы все фабрики, за исключением YourVendor\SomeModule\Model\GeneratedFactory, а после перевода Magento в production мод мы ставим readonly на все директории.

Есть два варианта как это исправить.
Первый вариант - написать фабрику GeneratedFactory, то есть она уже не будет генерируемой.
Второй вариант - переместить сласс SomeClass в директорию app/code/YourVendor/SomeModule, тогда наш сниффер обнаружит в классе SomeClass зависимость на генерируемую фабрику GeneratedFactory и кодогенератор ее сгенерирует.
А в точке входа my_api/index.php внести следующие изменения:

Второй пример

Неверное затягивание зависимостей.
Например, следующий код будет корректно работать в developer моде, но зафейлится в production.

Подобная конструкция может использоваться для добавления зависимостей при сохранении обратной совместимости. Но она имеет проблему схожую с первым примером, при выполнении команды bin/magento setup:di:compile генерируемая фабрика не сгенерируется.

Решить эту проблему можно также двумя способами.
Первый вариант - написать фабрику GeneratedFactory, то есть она уже не будет генерируемой.
Второй вариант - немного изменить конструктор:

Таким образом мы добавили новую зависимость, сохранили обратную совместимость и при этом все корректно будет генерироваться и работать в production моде.

Свои вопросы, предложения и пожелания пишите в комментариях :)