События в yii2

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: События в yii2

Сообщение svil »

У меня весь "Жунал" событий записывается в таблицу Tabl_for_events в БД, и если из этой таблицы
что-то удалить, то появляется также запись об этом, что не нужно.
Как исключить определенную модель из событий ?
Читала, что off. Но как?
Это для всех таблиц в БД:

Код: Выделить всё

  Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
            Yii::$app->db->createCommand()->insert('doing', ['content' =>  $event->sender->events(), 'type' => 'удален', 'user_id' => Yii::$app->user->identity->id, 'created_at' => time()])->execute();
        });
Если указываю

Код: Выделить всё

  Event::off("Tabl_for_events"::className(), ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
            //здесь срабатывает первый Event на все таблицы
        });
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: События в yii2

Сообщение svil »

Вот так "выпуталась":

Код: Выделить всё

 $par = get_class();
        if (!$par == "НАЗВАНИЕ КЛАССА::className()") {
    Event::on($par, ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
        Yii::$app->db->createCommand()->insert('таблица_для_журнала', ['content' => $event->sender->events(), 'type' => 'удален', 'user_id' => Yii::$app->user->identity->id, 'created_at' => time()])->execute();
    });
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: События в yii2

Сообщение yiiliveext »

Код: Выделить всё

Event::off("Tabl_for_events"::className(), ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
            //здесь срабатывает первый Event на все таблицы
        });
Во-первых так нельзя отключить обработчик-анонимную функцию. Во-вторых вы привязываете события на уровне ActiveRecord, а отвязать хотите на уровне потомка. Так не получится, Event::trigger(...) берет обработчики не только класса, для которого триггерится событие, а и его предков.

Код: Выделить всё

 $classes = array_merge(
            [$class],
            class_parents($class, true),
            class_implements($class, true)
        );

        foreach ($classes as $class) {
            $eventHandlers = [];
            
            if (!empty(self::$_events[$name][$class])) {
                $eventHandlers = array_merge($eventHandlers, self::$_events[$name][$class]);
            }

            foreach ($eventHandlers as $handler) {
                $event->data = $handler[1];
                call_user_func($handler[0], $event);
                if ($event->handled) {
                    return;
                }
            }
        }
И тут мы возвращаемся к старым методам) Достаточно прописать пустой метод afterDelete() в модели для которой нужно отключить событие afterDelete и оно больше возникать не будет.
Аватара пользователя
svil
Сообщения: 563
Зарегистрирован: 2018.02.12, 22:41

Re: События в yii2

Сообщение svil »

yiiliveext писал(а): 2019.08.28, 07:53 Достаточно прописать пустой метод afterDelete() в модели для которой нужно отключить событие afterDelete и оно больше возникать не будет.
А чтобы не возникали события Insert, Update что надо прописать в нужной модели (afterInsert, afterUpdate не помогло)?
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: События в yii2

Сообщение yiiliveext »

svil писал(а): 2019.08.28, 18:55
yiiliveext писал(а): 2019.08.28, 07:53 Достаточно прописать пустой метод afterDelete() в модели для которой нужно отключить событие afterDelete и оно больше возникать не будет.
А чтобы не возникали события Insert, Update что надо прописать в нужной модели (afterInsert, afterUpdate не помогло)?
пустой afterSave (или без parent::afterSave())
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: События в yii2

Сообщение ElisDN »

svil писал(а): 2019.08.28, 18:55 А чтобы не возникали события Insert, Update что надо прописать в нужной модели (afterInsert, afterUpdate не помогло)?
Не надо ничего отключать, ломая работу фреймворка. Просто добавьте условие в обработчик:

Код: Выделить всё

Event::on(ActiveRecord::class, ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
    if (get_class($event->sender) === TablForEvents::class) {
        return;
    }
    Yii::$app->db->createCommand()->insert(...)->execute();
});
Либо вместо навешивания на все ActiveRecord сделайте пустой interface Loggable {}, навесьте обработчик на него через Event::on(Loggable::class, ...) и добавьте implements Loggable нужным для логирования сущностям.
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: События в yii2

Сообщение yiiliveext »

ElisDN писал(а): 2019.08.28, 19:19
svil писал(а): 2019.08.28, 18:55 А чтобы не возникали события Insert, Update что надо прописать в нужной модели (afterInsert, afterUpdate не помогло)?
Не надо ничего отключать, ломая работу фреймворка. Просто добавьте условие в обработчик:

Код: Выделить всё

Event::on(ActiveRecord::class, ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
    if (get_class($event->sender) === TablForEvents::class) {
        return;
    }
    Yii::$app->db->createCommand()->insert(...)->execute();
});
Либо вместо навешивания на все ActiveRecord сделайте пустой interface Loggable {}, навесьте обработчик на него через Event::on(Loggable::class, ...) и добавьте implements Loggable нужным для логирования сущностям.
Каким образом это ломает работу фреймворка? Насчет интерфейса - согласен, тоже вариант, но нужно прописывать в каждой модели.
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: События в yii2

Сообщение yiiliveext »

yiiliveext писал(а): 2019.08.28, 19:35
ElisDN писал(а): 2019.08.28, 19:19
svil писал(а): 2019.08.28, 18:55 А чтобы не возникали события Insert, Update что надо прописать в нужной модели (afterInsert, afterUpdate не помогло)?
Не надо ничего отключать, ломая работу фреймворка. Просто добавьте условие в обработчик:

Код: Выделить всё

Event::on(ActiveRecord::class, ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
    if (get_class($event->sender) === TablForEvents::class) {
        return;
    }
    Yii::$app->db->createCommand()->insert(...)->execute();
});
Либо вместо навешивания на все ActiveRecord сделайте пустой interface Loggable {}, навесьте обработчик на него через Event::on(Loggable::class, ...) и добавьте implements Loggable нужным для логирования сущностям.
Каким образом это ломает работу фреймворка? Насчет интерфейса - согласен, тоже вариант, но нужно прописывать в каждой модели. Еще можно вынести TablForEvents в отдельный namespace и использовать wildcard.
Ответить