Проверка Laravel, если существует соответствующая модель

У меня есть модель Eloquent, у которой есть соответствующая модель:

public function option() { return $this->hasOne('RepairOption', 'repair_item_id'); } public function setOptionArrayAttribute($values) { $this->option->update($values); } 

когда я создаю модель, она не обязательно имеет связанную модель. Когда я его обновляю, я могу добавить опцию или нет.

Поэтому мне нужно проверить, существует ли соответствующая модель, либо обновить ее, либо создать ее соответственно:

 $model = RepairItem::find($id); if (Input::has('option')) { if (<related_model_exists>) { $option = new RepairOption(Input::get('option')); $option->repairItem()->associate($model); $option->save(); $model->fill(Input::except('option'); } else { $model->update(Input::all()); } }; 

Где <related_model_exists> – это код, который я ищу.

Хорошо, так как @TheShiftExchange не принял совета, там мы идем с общим решением, работающим на всех типах отношений:

 if (count($model->relation)) { // exists } 

Это будет работать для каждого отношения, так как динамические свойства возвращают Model или Collection . Оба реализуют ArrayAccess .

Так оно и происходит:

одиночные отношения: hasOne / принадлежит belongsTo / morphTo / morphOne

 // no related model $model->relation; // null count($model->relation); // 0 evaluates to false // there is one $model->relation; // Eloquent Model count($model->relation); // 1 evaluates to true 

to-many: hasMany / принадлежит belongsToMany / morphMany / morphToMany / morphedByMany

 // no related collection $model->relation; // Collection with 0 items evaluates to true count($model->relation); // 0 evaluates to false // there are related models $model->relation; // Collection with 1 or more items, evaluates to true as well count($model->relation); // int > 0 that evaluates to true 

Первое предложенное решение не будет работать для прежних отношений, так как на модели нет методов count() , и простая if ($model->relation) не будет оцениваться как false для любого из последних соотношений, так как существует всегда Коллекция. И это, даже пустое, всегда оценивает true .

Объект Relation передает неизвестные вызовы методов в конструктор запросов Eloquent , который настроен только для выбора связанных объектов. Этот Builder, в свою очередь, передает неизвестные вызовы методов в свой базовый запрос Builder .

Это означает, что вы можете использовать методы exists() или count() непосредственно из объекта отношения:

 $model->relation()->exists(); // bool: true if there is at least one row $model->relation()->count(); // int: number of related rows 

Обратите внимание на круглые скобки после relation : ->relation() – вызов функции (получение объекта отношения), а не ->relation которое для вас создал Lizardvel (получение связанного объекта / объекта).

Использование метода count объекта отношения (т. Е. Использование круглых скобок) будет намного быстрее, чем использование отношения $model->relation->count() или count($model->relation) (если отношение уже не было желательным – загружен), поскольку он запускает запрос на подсчет, а не вытягивает все данные для любых связанных объектов из базы данных, просто чтобы подсчитать их. Аналогичным образом, использование exists файла не обязательно должно выводить данные модели.

Both exists() и count() работают над всеми типами отношений, которые я пробовал, поэтому, по крайней мере, принадлежит belongsTo , hasOne , hasMany и принадлежит belongsToMany .

Я предпочитаю использовать exists метод:

RepairItem::find($id)->option()->exists()

чтобы проверить, существует ли соответствующая модель или нет. Он отлично работает на Laravel 5.2

Не уверен, что это изменилось в Laravel 5, но принятый ответ с использованием count($data->$relation) не работал для меня, так как сам процесс доступа к свойству отношения вызвал его загрузку.

В конце концов, простой isset($data->$relation) сделал для меня трюк.

Вы можете использовать метод relativeLoaded для объекта модели. Это спасло мой бекон, поэтому, надеюсь, это помогает кому-то другому. Мне дали это предложение, когда я задал тот же вопрос о Laracasts.