Всем привет. Данная публикация не претендует на звание истины в первой инстанции, а лишь является моим личным мнением, если вы его разделяете отлично, если нет — прошу в комментарии для обсуждения.
Так вот, ближе к делу. В версии Magento 2.3 и выше появилась такая «плюшка» как декларативная схема. Что же это такое декларативная схема? Если мы обратимся к документации мадженто, то там черным по белому написано — «Декларативая схема направлена на упрощение процессов установки и обновления Magento».
Вроде бы все здорово, ведь раньше разработчикам приходилось писать очень много install и upgrade скриптов (в М1 вообще был маленький кошмар с ними), вплоть до версии 2.3 нужно было в зависимости от задач держать энное количество скриптов, а именно:
InstallSchema — этот класс запускается при установке модуля для настройки структуры базы данных
InstallData — этот класс запускается при установке модуля для инициализации данных таблицы базы данных.
UpgradeSchema — этот класс запускается при обновлении модуля для настройки структуры базы данных
UpgradeData — этот класс запускается при обновлении модуля для добавления / удаления данных из таблицы.
Uninstall — этот класс запускается для удаления данных и таблиц из базы.
Согласитесь, это уже лучше чем для каждого чиха писать отдельный скрипт. Но и это оказалось не очень удобно, так как приходилось следить за версионностью, отслеживать и понимать что у тебя содержится в этих скриптах, и к тому же они разростались в огромные «портянки» на 4000+ строк. В итоге и этот подход оказался довольно провальным. Количество файлов сократилось, но количество строк кода увеличилось.
Тут то и пришла на помощь декларативная схема. По факту все свелось к одному файлу — db_schema.xml. В котором вы храните конечное состояние базы данных. То есть если вам для модуля нужна кастомная таблица, вы описываете нужные поля в данном файле и все. Дальше маджента сама для вас создаст таблицу. В случае если вам нужно обновить уже созданную ранее таблицу, вы просто вносите правки в файл db_schema.xml и все (магия произойдет сама). Не нужно следить за версионностью, не нужно для каждой новой версии модуля писать скрипты обновления базы, по факту не нужно делать лишних операция. Согласитесь — это круто.
Но ведь не бывает бочки дегтя без ложки дегтя. (Это не опечатка, кто работает с мадженто меня поймет :) ).
Декларативная схема хороша только при работе с кастомными таблицами. Если вам нужно добавить программно атрибут в продукт или категорию, сделать INSERT или UPDATE, или в конце концов изменить что-то в Schema — будьте любезны написать патчи. О них ниже и поговорим.
Для примера рассмотрим добавление кастомного атрибута для продукта.
1. Начнем с того, что в модуле создадим следующий класс:
Setup\Patch\Data\AddAlternativeNameAttribute.php
Который для начала будет содержать следующий контент
DataPatchInterface ожидает реализации трех функций: apply, getDependencies и getAliases.
2. Функция apply — место, где создаются элементы атрибутов. Теперь нет необходимости здесь вызывать функции startSetup и endSetup, ведь мы только создаем атрибуты. Для этого создаем экземпляр EavSetupFactory, передавая наш объект moduleDataSetup, и добавляем наш атрибут:
3. Функция getDependencies ожидает массив строк, который содержит имена классов зависимостей. Это новая функциональность, которая появилась специально для сценариев декларативной схемы, и она сообщает Magento, что нужно выполнить «патчи», которые мы здесь определили, перед нашим скриптом установки. Вот как Magento контролирует порядок выполнения скриптов патча.
4. Последняя функция getAliases, которая определяет псевдонимы для этого патча. Поскольку мы больше не указываем номера версий, имя нашего класса может измениться, и если это произойдет, мы должны указать здесь старое имя класса, чтобы оно не выполнялось во второй раз (патчи запускаются только один раз)
Итоговый класс будет выглядеть вот так:
5. Теперь запускаем bin/magento setup:upgrade для того, чтобы наш патч применился. Для всех патчей, которые успешно выполнены, Magento вставляет запись в таблицу базы данных patch_list со значением поля patch_name, равным значению нашего класса (Foo\Bar\Setup\Patch\Data\AddAlternativeNameAttribute).
6. Удаление значения из таблицы patch_list приведет к повторному выполнению патча при запуске установки bin/magento setup:upgrade. Данная функциональность будет полезна при отладке патчей.
Итог:
+ Декларативная схема упрощает работу с кастомными таблицами
+ Отсутствие надобности следить за версионностью
+ Легкий апгрейд данных в таблицах и кастомизация полей таблиц
— Отсутствие возможности добавлять атрибуты в продукт-категорию через декларативную схему
— Если модуль универсальный для версий 2.1, 2.2, 2.3 придется писать и декларативную схему и инсталл скрипты.
— Необходимость написания патчей для работы с core'вскими таблицами.
Возможно, в обозримом будущем, когда M2 полностью перейдет на декларативную схему и отпадет надобность писать патчи, это будет супер удобно. Но будет ли это и когда случится, вопрос остается открытым.
Так вот, ближе к делу. В версии Magento 2.3 и выше появилась такая «плюшка» как декларативная схема. Что же это такое декларативная схема? Если мы обратимся к документации мадженто, то там черным по белому написано — «Декларативая схема направлена на упрощение процессов установки и обновления Magento».
Вроде бы все здорово, ведь раньше разработчикам приходилось писать очень много install и upgrade скриптов (в М1 вообще был маленький кошмар с ними), вплоть до версии 2.3 нужно было в зависимости от задач держать энное количество скриптов, а именно:
InstallSchema — этот класс запускается при установке модуля для настройки структуры базы данных
InstallData — этот класс запускается при установке модуля для инициализации данных таблицы базы данных.
UpgradeSchema — этот класс запускается при обновлении модуля для настройки структуры базы данных
UpgradeData — этот класс запускается при обновлении модуля для добавления / удаления данных из таблицы.
Uninstall — этот класс запускается для удаления данных и таблиц из базы.
Согласитесь, это уже лучше чем для каждого чиха писать отдельный скрипт. Но и это оказалось не очень удобно, так как приходилось следить за версионностью, отслеживать и понимать что у тебя содержится в этих скриптах, и к тому же они разростались в огромные «портянки» на 4000+ строк. В итоге и этот подход оказался довольно провальным. Количество файлов сократилось, но количество строк кода увеличилось.
Тут то и пришла на помощь декларативная схема. По факту все свелось к одному файлу — db_schema.xml. В котором вы храните конечное состояние базы данных. То есть если вам для модуля нужна кастомная таблица, вы описываете нужные поля в данном файле и все. Дальше маджента сама для вас создаст таблицу. В случае если вам нужно обновить уже созданную ранее таблицу, вы просто вносите правки в файл db_schema.xml и все (магия произойдет сама). Не нужно следить за версионностью, не нужно для каждой новой версии модуля писать скрипты обновления базы, по факту не нужно делать лишних операция. Согласитесь — это круто.
Но ведь не бывает бочки дегтя без ложки дегтя. (Это не опечатка, кто работает с мадженто меня поймет :) ).
Декларативная схема хороша только при работе с кастомными таблицами. Если вам нужно добавить программно атрибут в продукт или категорию, сделать INSERT или UPDATE, или в конце концов изменить что-то в Schema — будьте любезны написать патчи. О них ниже и поговорим.
Для примера рассмотрим добавление кастомного атрибута для продукта.
1. Начнем с того, что в модуле создадим следующий класс:
Setup\Patch\Data\AddAlternativeNameAttribute.php
Который для начала будет содержать следующий контент
<?php
namespace Foo\Bar\Setup\Patch\Data;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
class AddAlternativeNameAttribute implements DataPatchInterface
{
/** @var ModuleDataSetupInterface */
private $moduleDataSetup;
/** @var EavSetupFactory */
private $eavSetupFactory;
/**
* @param ModuleDataSetupInterface $moduleDataSetup
* @param EavSetupFactory $eavSetupFactory
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
EavSetupFactory $eavSetupFactory
) {
$this->moduleDataSetup = $moduleDataSetup;
$this->eavSetupFactory = $eavSetupFactory;
}
}
DataPatchInterface ожидает реализации трех функций: apply, getDependencies и getAliases.
2. Функция apply — место, где создаются элементы атрибутов. Теперь нет необходимости здесь вызывать функции startSetup и endSetup, ведь мы только создаем атрибуты. Для этого создаем экземпляр EavSetupFactory, передавая наш объект moduleDataSetup, и добавляем наш атрибут:
/**
* {@inheritdoc}
*/
public function apply()
{
/** @var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
$eavSetup->addAttribute('catalog_product', 'alternative_name', [
'type' => 'varchar',
'label' => 'Alternative Name',
'input' => 'text',
'used_in_product_listing' => true,
'user_defined' => true,
]);
}
3. Функция getDependencies ожидает массив строк, который содержит имена классов зависимостей. Это новая функциональность, которая появилась специально для сценариев декларативной схемы, и она сообщает Magento, что нужно выполнить «патчи», которые мы здесь определили, перед нашим скриптом установки. Вот как Magento контролирует порядок выполнения скриптов патча.
/**
* {@inheritdoc}
*/
public static function getDependencies()
{
return [];
}
4. Последняя функция getAliases, которая определяет псевдонимы для этого патча. Поскольку мы больше не указываем номера версий, имя нашего класса может измениться, и если это произойдет, мы должны указать здесь старое имя класса, чтобы оно не выполнялось во второй раз (патчи запускаются только один раз)
/**
* {@inheritdoc}
*/
public function getAliases()
{
return [];
}
Итоговый класс будет выглядеть вот так:
<?php
namespace Foo\Bar\Setup\Patch\Data;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
class AddAlternativeNameAttribute implements DataPatchInterface
{
/** @var ModuleDataSetupInterface */
private $moduleDataSetup;
/** @var EavSetupFactory */
private $eavSetupFactory;
/**
* @param ModuleDataSetupInterface $moduleDataSetup
* @param EavSetupFactory $eavSetupFactory
*/
public function __construct(
ModuleDataSetupInterface $moduleDataSetup,
EavSetupFactory $eavSetupFactory
) {
$this->moduleDataSetup = $moduleDataSetup;
$this->eavSetupFactory = $eavSetupFactory;
}
/**
* {@inheritdoc}
*/
public function apply()
{
/** @var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
$eavSetup->addAttribute('catalog_product', 'alternative_name', [
'type' => 'varchar',
'label' => 'Alternative Name',
'input' => 'text',
'used_in_product_listing' => true,
'user_defined' => true,
]);
}
/**
* {@inheritdoc}
*/
public static function getDependencies()
{
return [];
}
/**
* {@inheritdoc}
*/
public function getAliases()
{
return [];
}
}
5. Теперь запускаем bin/magento setup:upgrade для того, чтобы наш патч применился. Для всех патчей, которые успешно выполнены, Magento вставляет запись в таблицу базы данных patch_list со значением поля patch_name, равным значению нашего класса (Foo\Bar\Setup\Patch\Data\AddAlternativeNameAttribute).
6. Удаление значения из таблицы patch_list приведет к повторному выполнению патча при запуске установки bin/magento setup:upgrade. Данная функциональность будет полезна при отладке патчей.
Итог:
+ Декларативная схема упрощает работу с кастомными таблицами
+ Отсутствие надобности следить за версионностью
+ Легкий апгрейд данных в таблицах и кастомизация полей таблиц
— Отсутствие возможности добавлять атрибуты в продукт-категорию через декларативную схему
— Если модуль универсальный для версий 2.1, 2.2, 2.3 придется писать и декларативную схему и инсталл скрипты.
— Необходимость написания патчей для работы с core'вскими таблицами.
Возможно, в обозримом будущем, когда M2 полностью перейдет на декларативную схему и отпадет надобность писать патчи, это будет супер удобно. Но будет ли это и когда случится, вопрос остается открытым.
maghamed
Вполне себе решенный вопрос, Magento 2.1 уже не поддерживается, а Мадженто 2.2 будет поддерживаться до декабря 2019 года, т.е. остался последний патч релиз 2.2.10 который выйдет в ближайший месяц.
magento.com/sites/default/files/magento-software-lifecycle-policy.pdf
Так что можете восприниматься, что М2 уже фактически полностью перешла на декларативную схему. Вопрос остается только с кастомизациями и экстеншенам, но с момента EOF 2.2 и они подтянутся.
aleeyt Автор
Пока в декларативной схеме смущает только написание патчей для работы с EAV. Хотя возможно уже есть механизмы которые позволяют добавлять атрибуты при помощи декларативной схеме, и я о них просто не знаю.