Не работает одно из событий в поведении

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
long399
Сообщения: 96
Зарегистрирован: 2019.08.13, 08:03
Откуда: г. Новосибирск

Не работает одно из событий в поведении

Сообщение long399 »

Здравствуйте, возникла одна проблема.

У меня реализовано поведение HistoryBehavior, которое отвечает за сохранение истории создания/редактирования моделей в коллекцию histrory (mongodb).

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

class HistoryBehavior extends Behavior
{
    const COLLECTION_NAME = 'history';

    /**
     * @var \yii\mongodb\Collection
     */
    private $collection;

    /**
     * @var \app\models\mongo\History
     */
    public $history;

    public function init()
    {
        parent::init();

        $this->collection = Yii::$app->mongodb->getCollection(self::COLLECTION_NAME);
    }

    public function events()
    {
        return [
            ActiveRecord::EVENT_AFTER_INSERT => 'addCreateInformation',
            ActiveRecord::EVENT_BEFORE_UPDATE => 'addUpdateInformation',
            ActiveRecord::EVENT_AFTER_FIND => 'initHistory',
        ];
    }

    /**
     * Добавление информации о создании
     * @return boolean
     */
    public function addCreateInformation($event)
    {
        ...
    }

    /**
     * Добавление информации о редактировании
     * @return boolean
     */
    public function addUpdateInformation($event)
    {
        ...
    }

    /**
     * Инициализация атрибута $history
     * @return boolean
     */
    public function initHistory($event)
    {
        $this->history = History::findOne($this->owner->_id);

        return true;
    }
}
События сохранения информации о создании/редактировании работают нормально. Не работает лишь событие EVENT_AFTER_FIND (метод initHistory()). Я понял, что это связано с тем, что в моей модели, в которой я подключаю данное поведение, есть переопределенный метод afterFind(), в котором я изменяю некоторые атрибуты, после их извлечения из mongodb.

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

public function afterFind()
    {
        // convert \MongoDB\BSON\UTCDateTime to string date format 'd.m.Y'
        $this->pass_date = date('d.m.Y', $this->pass_date->toDateTime()->getTimestamp());
        $this->date_start = date('d.m.Y', $this->date_start->toDateTime()->getTimestamp());
        $this->date_end = date('d.m.Y', $this->date_end->toDateTime()->getTimestamp());

        $this->department_id = $this->department_id['$id'];
        $this->shelf_life_id = $this->shelf_life_id['$id'];

        // set values for location object
        $this->location = new Location(
            $this->location['place']['$id'], $this->location['rack']['$id'],
            $this->location['shelf']['$id'], $this->location['shelf_place']
        );

        $this->tomes = $this->getTomesModels();
    }
Из-за этого метода, не работает событие инициализации истории, описанное в поведение. Подскажите, как сделать так, чтобы отработал и метод afterFind() в модели, и событие EVENT_AFTER_FIND в поведении?
long399
Сообщения: 96
Зарегистрирован: 2019.08.13, 08:03
Откуда: г. Новосибирск

Re: Не работает одно из событий в поведении

Сообщение long399 »

Получилось сделать, если в начале метода afterFind() в модели вызывать метод поведения.

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

public function afterFind()
    {
        $this->initHistory(new Event(['name' => $this::EVENT_AFTER_FIND, 'sender' => $this]));

        // convert \MongoDB\BSON\UTCDateTime to string date format 'd.m.Y'
        $this->pass_date = date('d.m.Y', $this->pass_date->toDateTime()->getTimestamp());
        $this->date_start = date('d.m.Y', $this->date_start->toDateTime()->getTimestamp());
        $this->date_end = date('d.m.Y', $this->date_end->toDateTime()->getTimestamp());

        $this->department_id = $this->department_id['$id'];
        $this->shelf_life_id = $this->shelf_life_id['$id'];

        // set values for location object
        $this->location = new Location(
            $this->location['place']['$id'], $this->location['rack']['$id'],
            $this->location['shelf']['$id'], $this->location['shelf_place']
        );

        $this->tomes = $this->getTomesModels();
    }
Не знаю насколько это правильно. Но вроде работает. Поправьте, если есть лучший вариант действий в подобной ситуации.
rak
Сообщения: 2181
Зарегистрирован: 2010.11.02, 23:40
Контактная информация:

Re: Не работает одно из событий в поведении

Сообщение rak »

при переопределении метода afterFind в модели нужно вызывать

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

parent::afterFind();
long399
Сообщения: 96
Зарегистрирован: 2019.08.13, 08:03
Откуда: г. Новосибирск

Re: Не работает одно из событий в поведении

Сообщение long399 »

rak писал(а): 2021.03.16, 11:56 при переопределении метода afterFind в модели нужно вызывать

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

parent::afterFind();
Спасибо, работает! Подскажите, принципиально ли где вызывать afterFind() для родительского класса? В начале или в конце методa?
rak
Сообщения: 2181
Зарегистрирован: 2010.11.02, 23:40
Контактная информация:

Re: Не работает одно из событий в поведении

Сообщение rak »

все зависит от ситуации: если нужно чтобы код в методе выполнился раньше, чем обработчики события, то в конце, в противном случае - в начале
Ответить