Баг в afterSave с changedAttributes?

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Баг в afterSave с changedAttributes?

Сообщение 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"
}
 
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Баг в afterSave с changedAttributes?

Сообщение zelenin »

var_dump($this->attributes);
var_dump($this->oldAttributes);

попробуйте это заменить на аналогичные геттеры для теста.
DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Re: Баг в afterSave с changedAttributes?

Сообщение DLST »

Ситуация не изменилась, у атрибута "number" по-прежнему стоит тип string.
Onotole
Сообщения: 1808
Зарегистрирован: 2012.12.24, 12:49

Re: Баг в afterSave с changedAttributes?

Сообщение Onotole »

Кстати да, я тоже такое заметил
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Баг в afterSave с changedAttributes?

Сообщение samdark »

Из формы прилетает? Из форм всё string...
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Баг в afterSave с changedAttributes?

Сообщение zelenin »

Sam Dark писал(а):Из формы прилетает? Из форм всё string...
$changedAttributes вычисляется из attributes и oldAttributes. Оба дампа в теме есть.
DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Re: Баг в afterSave с changedAttributes?

Сообщение DLST »

Sam Dark, да, данные прилетают из формы. Мне просто непонятно, почему, если значение не меняется у поля, оно все равно попадает в массив $changedAttributes? Если это не баг, то как тогда узнать измененные атрибуты в afterSave?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Баг в afterSave с changedAttributes?

Сообщение samdark »

Надо в валидаторы добавить приведение данных к int.
DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Re: Баг в afterSave с changedAttributes?

Сообщение DLST »

Sam Dark, спасибо, добавил новое правило валидации:

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

['number', 'filter', 'filter' => function($value) {
    return (int) $value;
}] 
и все заработало как нужно.
Sasha_ch
Сообщения: 80
Зарегистрирован: 2011.04.10, 15:59
Контактная информация:

Re: Баг в afterSave с changedAttributes?

Сообщение Sasha_ch »

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

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

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

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

$this->oldAttributes; // тут ТОЖЕ новые значения всех атрибутов
зачем oldAttributes нужен? во что я не вник? ) :oops:
CPU comparison platform: CPU Boss Multi language, Yii2 powered.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Баг в afterSave с changedAttributes?

Сообщение ElisDN »

Sasha_ch писал(а):зачем oldAttributes нужен? во что я не вник? ) :oops:
Для beforeSave.
Sasha_ch
Сообщения: 80
Зарегистрирован: 2011.04.10, 15:59
Контактная информация:

Re: Баг в afterSave с changedAttributes?

Сообщение Sasha_ch »

Дмитрий Спасибо!
P.S.Кстати за блог и за видео также Спасибо! )
CPU comparison platform: CPU Boss Multi language, Yii2 powered.
Loveorigami
Сообщения: 977
Зарегистрирован: 2014.08.27, 21:54

Re: Баг в afterSave с changedAttributes?

Сообщение 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 -
(до сохранения они одни, после сохранения - другие).
sokollondon
Сообщения: 2
Зарегистрирован: 2015.10.10, 14:30

Re: Баг в afterSave с changedAttributes?

Сообщение sokollondon »

Так проверить изменён ли атрибут в afterSave()

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

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

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