it-swarm.com.ru

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> - это код, который я ищу.

107
Tom Macdonald

В 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
146
Jarek Tkaczyk

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

Это означает, что вы можете использовать методы 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) (если только отношение не было загружено с нетерпением), так как он выполняет запрос подсчета, а не извлекает все данные для любые связанные объекты из базы данных, просто посчитать их. Аналогично, использование exists также не требует извлечения данных модели.

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

55
tremby

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

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

проверить, существует ли связанная модель или нет. На Laravel 5.2 работает нормально

16
Hafez Divandari

После Php 7.1 , принятый ответ не будет работать для всех типов отношений.

Поскольку в зависимости от типа отношения, Eloquent возвращает Collection, Model или Null. И в Php 7.1 count(null) сгенерирует error

Итак, чтобы проверить, существует ли отношение, вы можете использовать:

Для одиночных отношений: например, hasOne и belongsTo

if(!is_null($model->relation)) {
   ....
}

Для множественных отношений: Например: hasMany и belongsToMany

if ($model->relation->isNotEmpty()) {
   ....
}
7
Hemerson Varela

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

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

4
Dave Stewart

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

2
Anthony

Как уже сказал Хемерсон Варела в 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();
};
1
Adam

Вы сказали, что хотите проверить, существует ли отношение, поэтому вы можете сделать update или create. Однако в этом нет необходимости из-за метода updateOrCreate

Просто сделай это:

$model = RepairItem::find($id);
$model->option()
      ->updateOrCreate(['repair_item_id' => $model->id],['option' => 'A']);
0
Adam