Страница 1 из 1
сохранение модели в afterSave()
Добавлено: 2014.10.03, 11:24
t3rmit
Есть модель Post с полями
При создании поста нужно сохранять его урл в виде {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
Для 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
Пытаюсь сделать через стандартный 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);
}
Не проверял, но должно работать.