Страница 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 нужен? во что я не вник? )
Re: Баг в afterSave с changedAttributes?
Добавлено: 2016.06.15, 19:50
ElisDN
Sasha_ch писал(а):зачем oldAttributes нужен? во что я не вник? )
Для 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 присваиваются новые значения.