Laravel проверьте, существует ли связанная модель
У меня есть красноречивая модель, которая имеет связанную модель:
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>
- это код, который я ищу.
8 ответов:
на php 7.2+ вы не можете использовать
count
на объекте отношения, поэтому нет единого метода для всех отношений. Используйте метод запроса вместо того, как @tremby указано ниже:$model->relation()->exists()
универсальное решение, работающее на всех типах отношений (pre php 7.2):
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
ко-многим отношения:
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
A отношении объекта передает неизвестные вызовы метода через красноречивый конструктор запросов, который настроен только для выбора связанных объектов. Этот Строитель в свою очередь передает неизвестные вызовы методов через его базовый конструктор запросов.
это означает, что вы можете использовать
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
какой волшебный геттер свойств настроен для вас Laravel (получение связанного объекта/объектов).С помощью
count
метод на объекте отношения (то есть, используя круглые скобки) будет намного быстрее, чем делать$model->relation->count()
илиcount($model->relation)
(если отношение уже не было загружено), так как оно запускает запрос count, а не вытягивает все данные для любых связанных объектов из базы данных, просто чтобы посчитать их. Аналогично, используяexists
не нужно тянуть данные модели либо.и
exists()
иcount()
работа на всех типах отношений я пробовал, так что по крайней мереbelongsTo
,hasOne
,hasMany
иbelongsToMany
.
Я предпочитаю использовать
exists
способ:
RepairItem::find($id)->option()->exists()
чтобы проверить, если существует модель или нет. Он отлично работает на Laravel 5.2
после Php 7.1, принято отвечать не будет работать для всех типов отношений.
потому что в зависимости от типа отношения, красноречивый вернет a
Collection
, aModel
илиNull
. И в Php 7.1count(null)
появитсяerror
.Итак, чтобы проверить, существует ли связь, вы можете использовать:
для отношений одиночных: например
hasOne
иbelongsTo
if(!is_null($model->relation)) { .... }
для связи нескольких: Например:
hasMany
иbelongsToMany
if ($model->relation->isNotEmpty()) { .... }
Не уверен, что это изменилось в Laravel 5, но принятый ответ с помощью
count($data->$relation)
не сработало для меня, так как сам акт доступа к свойству relation вызвал его загрузку.В конце концов, простой
isset($data->$relation)
сделал трюк для меня.
можно использовать relationLoaded метод на объекте модели. Это спасло мой бекон, так что, надеюсь, это поможет кому-то еще. Я был учитывая это предложение когда я задал тот же вопрос о Laracasts.
как уже сказал Хемерсон Варела в Php 7.1
count(null)
появитсяerror
иhasOne
возвращаетnull
если строка не существует. Так как у вас естьhasOne
отношение я бы использовалempty
метод проверки:$model = RepairItem::find($id); if (!empty($temp = $request->input('option'))) { $option = $model->option; if(empty($option)){ $option = $user->expertise()->create(); } $option->someAttribute = temp; $option->save(); };
Вы сказали, что хотите проверить, если отношение уже существует, так что вы можете сделать
update
илиcreate
. Однако это не обязательно, из-за updateOrCreate метод.просто сделать это:
$model = RepairItem::find($id); $model->option() ->updateOrCreate(['repair_item_id' => $model->id],['option' => 'A']);