Страница 1 из 1
hasOne: возвращение объекта, даже если связь отсутствует
Добавлено: 2018.08.10, 11:21
GHopper
Приветствую.
Есть некоторая модель Book, у нее есть связанная модель Discount
Код: Выделить всё
/**
* @return \yii\db\ActiveQuery
*/
public function getDiscount()
{
return $this->hasOne(Discount::className(), ['book_id' => 'id']);
}
Эта связь
$book->discount используется в шаблонах для построения форм. Есть один нюанс - у книги не всегда есть скидка, т.е. может быть такое, что модель Discount для какой-то книги просто не существуе.
Вопрос:
Как переписать метод getDiscount, чтобы он всегда возвращал объект Discount (если не найдена модель, то возвращается просто
new Discount()). При этом этот метод должен дейстовать предсказуемо, т.е. при вызове
$book->getDiscount() мы получаем AR-объект, а
$book->discount сам объект Discount.
Re: hasOne: возвращение объекта, даже если связь отсутствует
Добавлено: 2018.08.10, 16:21
futbolim
Неправильная логика. Сделайте так:
$book->getDiscount() или $book->discount всегда указывает на объект связи таблицы discount. В $book->discount должен быть null при отсутствии связи. Там не нужен новый объект.
В зависимости от ситуации лучше создавайте новый объект отдельно, например, $new_discount. Или, если сильно хочется, добавьте поле в Книгу $book->newDiscount.
Управлять новым объектом можно в Book::afterFind(), Book::beforeValidate(), Book::afterSave() и остальных или где угодно (в контроллерах, поведениях, ...)
Re: hasOne: возвращение объекта, даже если связь отсутствует
Добавлено: 2018.08.10, 16:31
GHopper
Дело в том, что это не всегда удобно.
Во-первых, не хочу забивать таблицу discount путыми записями, чтобы всегда возвращался объект Discount по связи. Во-вторых, для формирования формы в представлении не хочу лишние условия "если есть связь, то давай ее, если связь пустая, то бери вот это". Проще переделать hasOne и всегда возвращать объект Discount. Сейчас, собственно, так и сделано, но проблема в том что этот метод вообще не умеет возвращать ActiveRecord-объект. А в оригинальном методе как-то сделано так, что $book->discount возвращает объект, а $book->getDiscount() возвращает ActiveRecord. Вот и я бы хотел сохранить эту логику в своем методе.
Re: hasOne: возвращение объекта, даже если связь отсутствует
Добавлено: 2018.08.10, 16:49
futbolim
"не хочу забивать таблицу discount путыми записями" - не забивайте.
Контроллер Вам в помощь для логики.
Re: hasOne: возвращение объекта, даже если связь отсутствует
Добавлено: 2018.08.10, 18:37
andku83
GHopper писал(а): ↑2018.08.10, 16:31
... Во-вторых, для формирования формы в представлении не хочу лишние условия "если есть связь, то давай ее, если связь пустая, то бери вот это". ...
Для формирования подобной формы лучше сделать модель для формы и уже у нее можно прикрутить нужную вам логику, вот вам
образец
Для редактирования подготовка выглядит так:
Код: Выделить всё
$model = new UserForm();
$model->setUser($this->findModel($id));
Re: hasOne: возвращение объекта, даже если связь отсутствует
Добавлено: 2018.08.10, 21:54
GHopper
andku83 писал(а): ↑2018.08.10, 18:37
GHopper писал(а): ↑2018.08.10, 16:31
... Во-вторых, для формирования формы в представлении не хочу лишние условия "если есть связь, то давай ее, если связь пустая, то бери вот это". ...
Для формирования подобной формы лучше сделать модель для формы и уже у нее можно прикрутить нужную вам логику, вот вам
образец
Для редактирования подготовка выглядит так:
Код: Выделить всё
$model = new UserForm();
$model->setUser($this->findModel($id));
Код: Выделить всё
/**
* @return UserProfile
*/
public function getUserProfile()
{
if ($this->userProfile === null) {
$this->userProfile = $this->getUser()->userProfile;
}
if ($this->userProfile === null) {
$this->userProfile = new UserProfile();
}
return $this->userProfile;
}
Вот и я так-же делаю сейчас. Но я думал есть более элегантное решение...