сохранение модели в afterSave()

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
t3rmit
Сообщения: 23
Зарегистрирован: 2014.04.29, 10:46

сохранение модели в afterSave()

Сообщение t3rmit » 2014.10.03, 11:24

Есть модель Post с полями

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

- id(primary key)
- title
- url
При создании поста нужно сохранять его урл в виде {id}-{title-in-translit}. Соответственно, сначала необходимо сохранить пост, а потом сформировать и сохранить поле url.
Пробовал сделать вторую часть в afterSave() модели

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

public function afterSave($insert, $changedAttributes)
    {
        $url = $this->id . "-";
        $url .= $this->createLatinUrl($this->title);
        $this->url = $url;
        if (!isset($changedAttributes["url"])) {
            $this->save();
        }
    }
но постонно сохранение вызывается рекурсивно, и сервер зависает.
Какое придумать условие, чтобы избежать рекурсии? Или как по другому решить?


t3rmit
Сообщения: 23
Зарегистрирован: 2014.04.29, 10:46

Re: сохранение модели в afterSave()

Сообщение t3rmit » 2014.10.03, 11:33

Вот такой вариант работает для вставки, но это не решает проблему с редактированием title

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

public function afterSave($insert, $changedAttributes)
{
        if ($insert) {
            $url = $this->id . "-";
            $url .= $this->createLatinUrl($this->title);
            $this->url = $url;
            if (!isset($changedAttributes["url"])) {
                $this->save();
            }
        }
}

t3rmit
Сообщения: 23
Зарегистрирован: 2014.04.29, 10:46

Re: сохранение модели в afterSave()

Сообщение t3rmit » 2014.10.03, 11:43

HQ0 писал(а):CActiveRecord::updateByPk
Для yii2.0 не нашел такого метода

Аватара пользователя
Faenir
Сообщения: 292
Зарегистрирован: 2010.01.06, 01:46
Откуда: Симферополь

Re: сохранение модели в afterSave()

Сообщение Faenir » 2014.10.03, 12:02

А зачем вам именно afterSave?
Можно ведь проще:

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

if($model->save()) {
    $model->updateSlug();
} 
Не понимаю, зачем хранить ID записи в поле url.

Лучше подключите в модели https://github.com/yiisoft/yii2/blob/ma ... havior.php для поля url и напишите геттер в модели:

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

public function getSlug() {
    return $this->id .'-'. $this->url;
}
Последний раз редактировалось Faenir 2014.10.03, 12:04, всего редактировалось 2 раза.

HQ0
Сообщения: 182
Зарегистрирован: 2012.10.17, 17:21

Re: сохранение модели в afterSave()

Сообщение HQ0 » 2014.10.03, 12:02

Версию проглядел. Действительно такого метода нет.
Можно сделать запрос прямо в мозг: https://github.com/yiisoft/yii2/blob/ma ... /db-dao.md

Аватара пользователя
vitalik1183
Сообщения: 1673
Зарегистрирован: 2014.07.01, 08:42

Re: сохранение модели в afterSave()

Сообщение vitalik1183 » 2014.10.03, 13:00

Я обычное такой функционал пихаю в поведение, насколько этот подход имеет жизнь?
Yii2!

HQ0
Сообщения: 182
Зарегистрирован: 2012.10.17, 17:21

Re: сохранение модели в afterSave()

Сообщение HQ0 » 2014.10.03, 13:04

Если этот фунцкионал может быть использовать еще раз — такой подход оправдан :)

Аватара пользователя
vitalik1183
Сообщения: 1673
Зарегистрирован: 2014.07.01, 08:42

Re: сохранение модели в afterSave()

Сообщение vitalik1183 » 2014.10.03, 13:05

Ну у меня к примеру генерация алиасов в 5 сущностях, поэтому решил вынести в поведение.
Yii2!

t3rmit
Сообщения: 23
Зарегистрирован: 2014.04.29, 10:46

Re: сохранение модели в afterSave()

Сообщение t3rmit » 2014.10.03, 13:27

Лучше подключите в модели https://github.com/yiisoft/yii2/blob/ma ... havior.php для поля url и напишите геттер в модели:
Пытаюсь сделать через стандартный SlaggableBehaviour

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

public function behaviors()
{
    [
                'class' => SluggableBehavior::className(),
                'attribute' => 'title',
                'slugAttribute' => 'url',
                'ensureUnique' => true,
                'uniqueSlugGenerator' =>
                    function($baseSlug, $iteration, $model)
                    {
                        return $model->id . Inflector::slug($model->title, "-");
                    },
    ],
} 
Для title = "Новая статья" сохраняет url = "novaa-stata". При этом id не добавляется. Как исправить?

Аватара пользователя
Faenir
Сообщения: 292
Зарегистрирован: 2010.01.06, 01:46
Откуда: Симферополь

Re: сохранение модели в afterSave()

Сообщение Faenir » 2014.10.03, 14:14

@var callable slug unique value generator. It is used in case [[ensureUnique]] enabled and generated slug is not unique.

t3rmit
Сообщения: 23
Зарегистрирован: 2014.04.29, 10:46

Re: сохранение модели в afterSave()

Сообщение t3rmit » 2014.10.03, 15:53

Если я пишу так, то ситуация та же. Не добавляет id. Как побороть?

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

public function behaviors()
    {
        return [           
            [
                'class' => SluggableBehavior::className(),
                'attribute' => 'title',
                'slugAttribute' => 'url',
                'ensureUnique' => true,
                'value' => function($event)
                {
                    return $this->id . Inflector::slug($this->title, "-");
                },
            ],
        ];
    }

Аватара пользователя
Faenir
Сообщения: 292
Зарегистрирован: 2010.01.06, 01:46
Откуда: Симферополь

Re: сохранение модели в afterSave()

Сообщение Faenir » 2014.10.03, 21:14

Потому что момент отработки SluggableBehavior записи в БД еще нет и ID - соответствено тоже.

Вообщем можно и в afterSave это сделать.
Нужно использовать не save() а updateAttributes() - он не вызывает afterSave().
Примерно так:

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

public function afterSave($insert, $changedAttributes)
{
    $this->url = $this->id .'-'. $this->createLatinUrl($this->title); // или $this->url = $this->id .'-'. Inflector::slug($this->title);
    $this->updateAttributes(['url']);
    parent::afterSave($insert, $changedAttributes);
}
Не проверял, но должно работать.

Ответить