Внедрение зависимостей в Magento 2 CRUD / Абстрактная модель

12

Можно ли ввести зависимость в модель CRUD Magento 2?

То есть - Magento 2 имеет базовый абстрактный класс модели: Magento\Framework\Model\AbstractModel. Если вы хотите создать простой объект модели Create, Read, Update, Delete, вы расширяете этот класс своим собственным классом.

class Foo extends Magento\Framework\Model\AbstractModel
{
}

Возможно ли внедрить зависимости в __constructметод вашей модели ? Когда я пытаюсь, я получаю следующую ошибку.

Неустранимая ошибка: невозможно создать экземпляр абстрактного класса Magento \ Framework \ Model \ ResourceModel \ AbstractResource

Преступник , кажется, AbstractModel«S __constructметод.

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {

Есть два типа подсказки в этом конструкторе ( Magento\Framework\Model\ResourceModel\AbstractResource, Magento\Framework\Data\Collection\AbstractDb), которые не Magento менеджер объекта интерфейсы. Это абстрактные классы. Когда я расширяю этот класс и пытаюсь добавить свою введенную зависимость

class Foo extends Magento\Framework\Model\AbstractModel
{
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
        \Package\Module\Model\Mine $mine,

    ) {
        //...
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);

    }
}

Magento запускается, когда менеджер объектов пытается создать экземпляр абстрактных классов.

Я могу «исправить» это, переместив мою объектную зависимость перед абстрактными классами

    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,

        \Package\Module\Model\Mine $mine,

        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
    ) {  

Однако это изменило порядок аргументов. В классе, который полностью управляется объектами, это не будет проблемой. Однако тот факт, что эти абстрактные подсказки типов классов существуют, подразумевает, что есть части системы Magento, которые будут вручную (т.е. не через диспетчер объектов или DI) создавать экземпляры объектов CRUD и передавать объекты, которые соответствуют подсказкам типов в этом конкретном порядке .

Это безопасно? т.е. являются ли эти абстрактные классы в конструкторе абстрактной модели просто устаревшим кодом и не используются? Или части системы все еще будут использовать их, что означает, что невозможно внедрить зависимости в модель CRUD?

Алан Сторм
источник

Ответы:

9

Прежде всего конструктор является приватным API класса. Функция конструктора имеет особое значение и не требует наличия того же списка / порядка аргументов, что и в родительском классе.

Можно ли ввести зависимость в модель CRUD Magento 2?

Да, конечно.

Это безопасно?

Да, но Magento Object Manager предполагает, что все необязательные параметры помещаются в конец списка, а обязательные параметры после необязательных не разрешаются.

Аргументы $ resource, $ resourceCollection являются устаревшими, но все еще широко используются в классах Model. Большая часть модели использует подобный код для инициализации ресурса и класса коллекции.

protected function _construct() { 
    $this->_init('Magento\AdminNotification\Model\Resource Model\Inbox'); 
}

Вот почему эти параметры не являются обязательными. Но, например, в модульном тесте мы передаем макет ресурса или коллекции в конструктор, чтобы позволить реализацию замены.

Канди
источник
@Kanday Инженерно-архитектурный отдел Magento когда-либо публично заявлял, что заказ конструктора для базовых классов не имеет значения? Или это просто надежда большинства людей, работающих над этим?
Алан Сторм
Я не буду называть это "неактуально". Просто OM передаст необходимые аргументы вашему конструктору, и это не зависит от порядка в родительском классе. Более того, IN использует имена параметров, так что теперь лучше не менять их (это отличается от языка php, где вы можете изменять имена параметров по
своему усмотрению
Я не уверен, что понимаю, что вы говорите. Вы говорите, что в какой-то момент в будущем основной системный код Magento может снова начать рассматривать порядок аргументов / параметров как существенный?
Алан Сторм
Я считаю, что нет
KAndy
Спасибо еще раз! FWIW, и для Google, кажется, это должно быть безопасным делом. Из того, что я могу сказать, нет системного кода Magento, который автоматически слепо создает модель, предполагающую порядок параметров конструктора.
Алан Сторм
6

Это кажется безопасным. По крайней мере, Мадженто делает это во многих местах. Смотрите примеры методов __construct в следующем (неисключительном) списке классов.

  • \ Magento \ Theme \ Model \ Theme \ File
  • \ \ Magento Theme \ Model \ Design
  • \ Magento \ Sales \ Model \ Order \ Creditmemo

К сожалению, я не могу ответить на другую часть вашего вопроса.

Натан Тоомбс
источник
4
  1. Как вы используете свою модель?
  2. В вашем случае $mineэто требуется параметр, в то время $resource, $resourceCollectionи $dataявляются по желанию . Необязательные параметры всегда должны быть последними, иначе с ними просто невозможно работать, как с необязательными. Так что мне кажется, что вы должны указать $mineлюбые необязательные параметры.
BuskaMuza
источник
За исключением тех абстрактных параметров, которые не являются параметрами, введенными зависимостями, и если системный код ядра Magento ожидает, что их перемещение $mineв начало очереди приведет к ошибкам. Если системный код Magento не использует их, то почему они там? Вот вопрос, который я пытаюсь понять до конца. То, что я могу использовать свою модель с перемещенным параметром, не делает ее безопасной.
Алан Сторм
Некоторые модели могут по-прежнему использовать эти необязательные параметры для передачи пользовательской модели ресурсов. Например, github.com/magento/magento2/blob/develop/app/code/Magento/...
BuskaMuza
Magento использует отражение, чтобы определить, является ли параметр необязательным или нет. И PHP считает все параметры, стоящие перед обязательным параметром, обязательными . Таким образом, если вы перемещаетесь $mineперед необязательными параметрами, они становятся действительно необязательными, и Magento просто передает значения по умолчанию ( null, array()). Если вы ставите обязательный параметр после необязательных, PHP рассматривает необязательные параметры как обязательные, и Magento пытается их создать (но для них нет предпочтений).
BuskaMuza
Хотя я согласен, что это выглядит сбивающим с толку, и, возможно, мы могли бы просто установить предпочтение абстрактным классам вместо того, чтобы обрабатывать их внутри класса модели. Таким образом, реальный объект всегда вводится.
BuskaMuza