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, принято отвечать не будет работать для всех типов отношений.
потому что в зависимости от типа отношения, Eloquent вернет Collection
, a Model
или Null
. И в Php 7.1 count(null)
появится error
.
Итак, чтобы проверить, существует ли отношение, вы можете использовать:
для отношений single: например hasOne
и belongsTo
if(!is_null($model->relation)) {
....
}
для связи нескольких: Например:hasMany
и belongsToMany
if ($model->relation->isNotEmpty()) {
....
}
не уверен, что это изменилось в Laravel 5, но принятый ответ с использованием count($data->$relation)
не сработало для меня, так как сам акт доступа к свойству relation вызвал его загрузку.
В конце концов, простой isset($data->$relation)
сделал трюк для меня.
можно использовать relationLoaded метод на объекте модели. Это спасло мой бекон, надеюсь, это поможет кому-то еще. Я был учитывая это предложение когда я задал тот же вопрос о Laracasts.
как Варела Hemerson уже сказал в 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']);