Страница 1 из 1

Баг в afterSave с changedAttributes?

Добавлено: 2015.04.03, 13:22
DLST
Если у свойства модели тип является int, то независимо от того, меняли ли мы это значение, оно все равно попадает в массив $changedAttributes. Может быть я чего-то не понимаю или делаю не так?

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

/**
 * This is the model class for table "test".
 *
 * @property integer $id
 * @property string $string
 * @property integer $number
 */
class Test extends \yii\db\ActiveRecord
{
    public static function tableName()
    {
        return 'test';
    }

    public function rules()
    {
        return [
            [['number'], 'integer'],
            [['string'], 'string', 'max' => 100]
        ];
    }

    public function afterSave($insert, $changedAttributes)
    {
        echo "<pre>";
        var_dump($changedAttributes);
        var_dump($this->attributes);
        var_dump($this->oldAttributes);
        echo "</pre>";
        exit;
        parent::afterSave($insert, $changedAttributes);
    }
}
Вывод var_dump:

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

array(1) {
  ["number"]=>
  int(1)
}
array(3) {
  ["id"]=>
  int(1)
  ["string"]=>
  string(4) "test"
  ["number"]=>
  string(1) "1"
}
array(3) {
  ["id"]=>
  int(1)
  ["string"]=>
  string(4) "test"
  ["number"]=>
  string(1) "1"
}
 

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.03, 13:39
zelenin
var_dump($this->attributes);
var_dump($this->oldAttributes);

попробуйте это заменить на аналогичные геттеры для теста.

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.03, 13:48
DLST
Ситуация не изменилась, у атрибута "number" по-прежнему стоит тип string.

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.03, 17:55
Onotole
Кстати да, я тоже такое заметил

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.03, 21:08
samdark
Из формы прилетает? Из форм всё string...

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.03, 21:11
zelenin
Sam Dark писал(а):Из формы прилетает? Из форм всё string...
$changedAttributes вычисляется из attributes и oldAttributes. Оба дампа в теме есть.

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.04, 00:19
DLST
Sam Dark, да, данные прилетают из формы. Мне просто непонятно, почему, если значение не меняется у поля, оно все равно попадает в массив $changedAttributes? Если это не баг, то как тогда узнать измененные атрибуты в afterSave?

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.04, 23:30
samdark
Надо в валидаторы добавить приведение данных к int.

Re: Баг в afterSave с changedAttributes?

Добавлено: 2015.04.06, 11:19
DLST
Sam Dark, спасибо, добавил новое правило валидации:

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

['number', 'filter', 'filter' => function($value) {
    return (int) $value;
}] 
и все заработало как нужно.

Re: Баг в afterSave с changedAttributes?

Добавлено: 2016.06.15, 19:00
Sasha_ch
периодически в afterSave напарываюсь и ищу старое значение в $this->oldAttributes, хотя на самом то деле :

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

$changedAttributes; // тут старые значения измененных атрибутов

$this->attributes; // тут новые значения всех атрибутов

$this->oldAttributes; // тут ТОЖЕ новые значения всех атрибутов
зачем oldAttributes нужен? во что я не вник? ) :oops:

Re: Баг в afterSave с changedAttributes?

Добавлено: 2016.06.15, 19:50
ElisDN
Sasha_ch писал(а):зачем oldAttributes нужен? во что я не вник? ) :oops:
Для beforeSave.

Re: Баг в afterSave с changedAttributes?

Добавлено: 2016.06.16, 14:10
Sasha_ch
Дмитрий Спасибо!
P.S.Кстати за блог и за видео также Спасибо! )

Re: Баг в afterSave с changedAttributes?

Добавлено: 2017.12.01, 13:21
Loveorigami
Замучался искать решение, тем не менее...

Есть некое событие, которое пишет значения в лог.

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

        // Запись в лог
        Event::on(AkciiData::class, AkciiData::EVENT_AFTER_UPDATE, [
            AkciiDataLogHandler::class, AkciiDataLogHandler::HANDLER_LOG
        ]);
Менеджеру нужно знать, что, когда и насколько изменили.

По наитию написал

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

<?php

class AkciiData extends ActiveRecord
{
    .........................
    /**
     * @return bool
     */
    public function isSkidkaChanged()
    {
        return $this->getOldSkidka() != $this->getNewSkidka();
    }

     /**
     * @return integer
     */
    public function getNewSkidka()
    {
        return $this->skidka;
    }

    /**
     * @return integer
     */
    public function getOldSkidka()
    {
        return ArrayHelper::getValue($this->oldAttributes, 'skidka');
    }

}

Надеясь получить в событии два значения

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


class AkciiDataLogHandler
{
    const HANDLER_LOG = 'addToLog';

    public static function addToLog($event)
    {
        /** @var AkciiData $data */
        $data = $event->sender;

        echo $data->getOldSkidka();
        echo $data->getNewSkidka();
        
        exit();

        if ($data->isSkidkaChanged()) {
            AkciiDataLog::create($data);
        }
    }
}
Но приходит постоянно одно и то же новое значение.

Пока что для себя решил так.
Добавил метод afterSave со следующим

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

    /**
     * @param bool $insert
     * @param array $changedAttributes
     */
    public function afterSave($insert, $changedAttributes)
    {
        $this->setOldAttributes($changedAttributes);
        parent::afterSave($insert, $changedAttributes);
    }

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

Может, можно $this->setOldAttributes($changedAttributes); добавить в сам фреймворк, чтоб не было путаницы, как выше с $oldAttribues -
(до сохранения они одни, после сохранения - другие).

Re: Баг в afterSave с changedAttributes?

Добавлено: 2021.10.01, 13:06
sokollondon
Так проверить изменён ли атрибут в afterSave()

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

public function afterSave($insert, $changedAttributes){
    //isAttributeChangedAfterSave
    var_dump(array_key_exists('name', $changedAttributes) && $this->name != $changedAttributes['name']);

    //...
}
Помните, что isAttributeChanged() не работает в afterSave(), т.к. после сохранения в $this->oldAttributes присваиваются новые значения.