Баг в afterSave с changedAttributes?

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

Баг в afterSave с changedAttributes?

Сообщение DLST » 2015.04.03, 13:22

Если у свойства модели тип является 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
Сообщения: 10146
Зарегистрирован: 2013.04.20, 11:30

Re: Баг в afterSave с changedAttributes?

Сообщение zelenin » 2015.04.03, 13:39

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

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

DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Re: Баг в afterSave с changedAttributes?

Сообщение DLST » 2015.04.03, 13:48

Ситуация не изменилась, у атрибута "number" по-прежнему стоит тип string.

Onotole
Сообщения: 1808
Зарегистрирован: 2012.12.24, 12:49

Re: Баг в afterSave с changedAttributes?

Сообщение Onotole » 2015.04.03, 17:55

Кстати да, я тоже такое заметил

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

Re: Баг в afterSave с changedAttributes?

Сообщение samdark » 2015.04.03, 21:08

Из формы прилетает? Из форм всё string...

zelenin
Сообщения: 10146
Зарегистрирован: 2013.04.20, 11:30

Re: Баг в afterSave с changedAttributes?

Сообщение zelenin » 2015.04.03, 21:11

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

DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Re: Баг в afterSave с changedAttributes?

Сообщение DLST » 2015.04.04, 00:19

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

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

Re: Баг в afterSave с changedAttributes?

Сообщение samdark » 2015.04.04, 23:30

Надо в валидаторы добавить приведение данных к int.

DLST
Сообщения: 7
Зарегистрирован: 2014.08.27, 11:11

Re: Баг в afterSave с changedAttributes?

Сообщение DLST » 2015.04.06, 11:19

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

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

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

Sasha_ch
Сообщения: 70
Зарегистрирован: 2011.04.10, 15:59
Откуда: Киев

Re: Баг в afterSave с changedAttributes?

Сообщение Sasha_ch » 2016.06.15, 19:00

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

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

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

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

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

Аватара пользователя
ElisDN
Сообщения: 4636
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Баг в afterSave с changedAttributes?

Сообщение ElisDN » 2016.06.15, 19:50

Sasha_ch писал(а):зачем oldAttributes нужен? во что я не вник? ) :oops:
Для beforeSave.
Не забудьте пройти мастер-класс по Yii2.

Sasha_ch
Сообщения: 70
Зарегистрирован: 2011.04.10, 15:59
Откуда: Киев

Re: Баг в afterSave с changedAttributes?

Сообщение Sasha_ch » 2016.06.16, 14:10

Дмитрий Спасибо!
P.S.Кстати за блог и за видео также Спасибо! )

Loveorigami
Сообщения: 705
Зарегистрирован: 2014.08.27, 21:54

Re: Баг в afterSave с changedAttributes?

Сообщение Loveorigami » 2017.12.01, 13:21

Замучался искать решение, тем не менее...

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

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

        // Запись в лог
        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 -
(до сохранения они одни, после сохранения - другие).

Ответить