Выполнить код, когда модель Eloquent извлекается из базы данных

У меня модель Eloquent. Всякий раз, когда он извлекается из базы данных, я хотел бы проверить, выполнено ли условие, и установить атрибут модели, если это так.

РЕДАКТИРОВАТЬ: я изначально думал, что событие restoring будет подходящим местом для размещения соответствующей логики, но, как указывает Тайлер Кромптон ниже, restoring запускается до восстановления обратимо удаленной записи.


person severin    schedule 18.09.2013    source источник
comment
проверить событие retrieved laravel.com/docs/5.5/eloquent#events   -  person Jeff Puckett    schedule 12.05.2018


Ответы (3)


У вас есть два допустимых варианта:

На вашем месте я бы выбрал первый вариант и сделал бы так:

<?php namespace \Illuminate\Database\Eloquent;

abstract class LoadingModel extends Model {

    /**
     * Register a loaded model event with the dispatcher.
     *
     * @param  \Closure|string  $callback
     * @return void
     */
    public static function loaded($callback)
    {
        static::registerModelEvent('loaded', $callback);
    }

    /**
     * Get the observable event names.
     *
     * @return array
     */
    public function getObservableEvents()
    {
        return array_merge(parent::getObservableEvents(), array('loaded'));
    }

    /**
     * Create a new model instance that is existing.
     *
     * @param  array  $attributes
     * @return \Illuminate\Database\Eloquent\Model|static
     */
    public function newFromBuilder($attributes = array())
    {
        $instance = parent::newFromBuilder($attributes);

        $instance->fireModelEvent('loaded', false);

        return $instance;
    }

}

Просто убедитесь, что рассматриваемые модели подкласса от LoadingModule. Я подтвердил, что это работает, так как нашел для него отличный вариант использования. Старые версии PHP возвращали значения MySQL в виде строк. Обычно PHP молча приводит их к соответствующим числовым типам в числовых операциях. Однако преобразование в JSON не считается числовой операцией. Значения JSON представлены в виде строк. Это может вызвать проблемы у клиентов моего API. Поэтому я добавил в свои модели событие loaded для преобразования значений в правильный тип.

person Tyler Crompton    schedule 04.01.2014
comment
Спасибо!! Это действительно работает, и довольно странно, что они не добавят это событие в модель красноречивого: есть событие для всего, но не для извлечения данных из базы данных! Спасибо! :) - person Alessio Periloso; 31.10.2014
comment
@AlessioPeriloso, я думаю, они этого не хотят, потому что это всего лишь один дополнительный вызов функции для каждой модели в уже тяжелой структуре. Недостаточно вариантов использования, которые требуют этого. А варианты использования, которые вы можете придумать, могут быть решены альтернативными (пусть и менее семантическими) средствами. - person Tyler Crompton; 01.11.2014
comment
Вариант 3: переопределить newFromBuilder в вашей конкретной модели и делать все, что вы хотели сделать в обработчике событий. Довольно хакерский, но может быть достаточно хорош для разовых действий. - person joerx; 04.02.2015

Вы можете сделать это на входе или на выходе. Похоже, вы хотели сохранить его в базе данных, чтобы использовать мутаторы.

class Foo extends Eloquent {

    public function setBAttribute($value)
    {
        if ($this->attributes['a'] == $this->attributes['b']) {
            $this->attributes['b'] = 1;
        }
    }    
}

Когда когда-либо устанавливается B, он будет сверяться с A и сохранять 1 в B.

Примечание. Обратите внимание на B между набором и атрибутом.

person Chris    schedule 05.01.2014

Я думаю, что это лучший вариант, который вы можете использовать.

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

self::retrieved(function (self $model){
   //all your code here
});
person Peter    schedule 09.07.2021