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

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

Добавлено: 2014.10.03, 11:24
t3rmit
Есть модель 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();
        }
    }
но постонно сохранение вызывается рекурсивно, и сервер зависает.
Какое придумать условие, чтобы избежать рекурсии? Или как по другому решить?

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

Добавлено: 2014.10.03, 11:31
HQ0

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

Добавлено: 2014.10.03, 11:33
t3rmit
Вот такой вариант работает для вставки, но это не решает проблему с редактированием 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();
            }
        }
}

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

Добавлено: 2014.10.03, 11:43
t3rmit
HQ0 писал(а):CActiveRecord::updateByPk
Для yii2.0 не нашел такого метода

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

Добавлено: 2014.10.03, 12:02
Faenir
А зачем вам именно 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;
}

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

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

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

Добавлено: 2014.10.03, 13:00
vitalik1183
Я обычное такой функционал пихаю в поведение, насколько этот подход имеет жизнь?

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

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

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

Добавлено: 2014.10.03, 13:05
vitalik1183
Ну у меня к примеру генерация алиасов в 5 сущностях, поэтому решил вынести в поведение.

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

Добавлено: 2014.10.03, 13:27
t3rmit
Лучше подключите в модели 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 не добавляется. Как исправить?

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

Добавлено: 2014.10.03, 14:14
Faenir
@var callable slug unique value generator. It is used in case [[ensureUnique]] enabled and generated slug is not unique.

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

Добавлено: 2014.10.03, 15:53
t3rmit
Если я пишу так, то ситуация та же. Не добавляет id. Как побороть?

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

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

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

Добавлено: 2014.10.03, 21:14
Faenir
Потому что момент отработки 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);
}
Не проверял, но должно работать.