Плагины для магических добытчиков / сеттеров

9

Я пытаюсь сделать так, чтобы статус отзыва был approvedвместо того, pendingчтобы пользователь публиковал его во внешнем интерфейсе в Magento 2.
И я воспользовался этим подходом. Создание до плагин, доступный только в области внешнего интерфейса, для метода setStatusIdдля того, Magento\Review\Model\Reviewчто выглядит следующим образом

public function beforeSetStatusId(\Magento\Review\Model\Review $review, $status)
{
    return [\Magento\Review\Model\Review::STATUS_APPROVED];
}

Это показалось мне хорошей идеей. И это должно работать, так как я возвращаю одобренный статус. Фактический метод должен затем выбрать это в качестве параметра.
но, к моему удивлению, это не сработало.
Затем я выкопал и обнаружил, что метод setStatusIdне существует в модели обзора. Это волшебно называется, и это на самом деле работает setData('status_id', $status).
Я посмотрел тогда в сгенерированном перехватчике, и, действительно, нет setStatusIdметода.

Как я могу подключить магические геттеры / сеттеры в magento 2? Это вообще возможно?

Примечание: мне не нужно решение для автоматического подтверждения отзывов. Я знаю, что могу использовать другие подходы, такие как save_beforeсобытия. Это не важно сейчас.

Мариус
источник

Ответы:

14

Это вообще возможно?

Да.

Как я могу подключить магические геттеры / сеттеры в magento 2?

Так же, как и другой публичный метод. Вам необходимо объявить плагин в di.xmlконфигурации и добавить свой собственный код в плагин.

public function before__call(\Magento\Review\Model\Review $review, $method, $args)
{
    if ($method == 'setStatusId') {
        if (isset($args[0])) {
            $args[0] = \Magento\Review\Model\Review::STATUS_APPROVED;
            return [$method, $args];
        }
    }
    //leave everything unchanged
    return null;
}

Но плагинизация классов DTO не очень хорошая идея. Попробуйте настроить соответствующие контроллеры / службы для изменения поведения приложения и не добавляйте плагины на объект DTO. Эта настройка уничтожит слои приложения . Я понимаю, что вы используете самый быстрый и легкий способ, но в некоторых случаях это неправильная стратегия.

Максимум
источник
Я согласен с вами по настройке. Это было просто доказательство концепции.
Мариус
@Мариус, да, круто
Макс
Я выбрал этот подход, но он потерпит неудачу, когда / если модуль обзора будет реорганизован для использования сервисных контрактов. Пока все нормально. Спасибо.
Мариус
да, конечно, но ваш вопрос был «Как я могу подключить магические геттеры / сеттеры в magento 2? Это вообще возможно?». Лучшим вариантом было бы использовать плагины только для общедоступных методов и сервисов API, но в некоторых модулях magento отсутствуют какие-либо API или они плохие.
Макс
4

У меня когда-то была похожая проблема. Я закончил с плагином -методом setData(), хотя, по моему мнению, это порождает огромную трату ресурсов ... :-(

Гиль Беркерс
источник
Хорошо. это рабочий подход. +1. Но я надеюсь на более чистый вариант (при условии, что он есть).
Мариус
Я надеюсь на то же самое. Я все еще плачу себе каждую ночь, потому что это исправление выглядит таким грязным. Я думаю, что единственная причина, по которой все еще существуют магические методы, заключается в унаследованном коде Magento 1. Я думаю, что пока модель обзора еще не реорганизована в модель данных, вам не повезло с этой моделью.
Giel Berkers
Я понял, что это из-за устаревшего кода. И я извлек из этого хороший урок. Не полагайтесь на магию для пользовательских модулей CRUD.
Мариус
Я использовал подход, объясненный Максом здесь, главным образом потому, что мой плагин будет вызываться только тогда, когда вызывается магический установщик, а не для всех setDataвызовов. Это не идеально, но это немного лучше, чем использовать setData. Может быть, вы можете изменить свой подход и спать немного лучше ночью. :)
Мариус