Laravel Check 관련 모델이 존재하는 경우


151

관련 모델이있는 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>내가 찾고있는 코드는 어디에 있습니까 ?


3
멋진 질문 감사합니다! 그리고 아래 사람들에 대한 훌륭한 답변. 프로젝트 시간을 절약했습니다.
Rafael

답변:


197

PHP 7.2 이상 에서는 count관계 객체를 사용할 수 없으므로 모든 관계에 대해 하나의 모든 방법이 없습니다. 아래 제공된 @tremby와 같이 대신 쿼리 방법을 사용하십시오.

$model->relation()->exists()

모든 관계 유형에서 작동하는 일반 솔루션 ( php 7.2 이전 ) :

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

동적 속성을 반환하기 때문에이 모든 관계에 대해 작동합니다 ModelCollection. 둘 다 구현 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

1
모든 것을 읽으십시오. count($relation)모든 관계에 대한 일반적인 솔루션입니다. 그것은을 위해 작동 Model하고 Collection있는 동안, Model더없는 ->count()방법을.
Jarek Tkaczyk

7
@CurvianVynes 아닙니다. Collection자체 메서드 isEmpty가 있지만 일반 empty함수는 객체에 대해 false를 반환합니다 (따라서 빈 컬렉션에는 작동하지 않음).
Jarek Tkaczyk

1
count($model->relation)morphTo관계에 아직 연관이 설정되지 않은 경우 에는 작동하지 않았습니다. 외래 ID와 유형이 null이며 Laravel이 작성한 db 쿼리는 가짜이며 예외가 발생합니다. $model->relation()->getOtherKey()해결 방법으로 사용 했습니다.
Jocelyn

1
@Jocelyn 네, Eloquent 버그입니다. 불행히도 다형성 관계에 대한 최소한 몇 가지가 있으므로 분명히 어떤 식 으로든 의존 할 수는 없습니다.
Jarek Tkaczyk 2014

2
PHP 7.2에서 다음을 반환합니다.count(): Parameter must be an array or an object that implements Countable
CodeGodie

81

관계 객체는 을 통해 알 수없는 메소드 호출에 전달 웅변 쿼리 빌더 에만 관련 개체를 선택하도록 설정되어 있습니다. 빌더 턴에 이르기까지 알 수없는 메소드 호출 전달 기본 쿼리 빌더 .

이는 관계 객체에서 직접 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에 의해 당신을 위해 설정 마법 속성 게터는 (관련 객체 / 객체를 받고).

은 Using count(괄호를 사용)의 관계 개체의 방법은 훨씬 더 빨리하는 것보다 것 $model->relation->count()또는 count($model->relation)그것을 실행하기 때문에 (의 관계는 이미 열망로드되지 않는 한) 카운트 쿼리가 아니라 관련된 모든 개체에 대한 모든 데이터를 당기는 것보다 데이터베이스에서 계산하기 만하면됩니다. 마찬가지로를 사용 exists하면 모델 데이터를 가져올 필요가 없습니다.

모두 exists()count()내가 해봤 모든 관계 유형에 대한 작업, 너무 적어도 belongsTo, hasOne, hasMany,와 belongsToMany.


루멘에 존재하지 않는 이유는 확실하지 않습니다.
briankip

@ briankip-그래야합니다. 마술 속성을 사용하여 컬렉션이 아닌 메소드를 호출하여 관계 객체를 얻었습니까?
tremby 2011

18

exists방법 을 사용하는 것을 선호합니다 .

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

관련 모델이 존재하는지 확인합니다. Laravel 5.2에서 잘 작동합니다.


1
+1; 관계 테이블에 항목이 없어도 Laravel 5.2에서는 count ($ model-> relation)가 true로 반환되었습니다. -> exists ()가 트릭을 수행합니다.
벤 윌슨

9

Php 7.1 이후 에는 허용 된 답변이 모든 유형의 관계에 적용되지 않습니다.

관계 유형에 따라 Eloquent는 a Collection, a Model또는을 반환합니다 Null. 그리고 Php 7.1 count(null) 에서는 error.

따라서 관계가 존재하는지 확인하려면 다음을 사용할 수 있습니다.

관계를위한 단일 예를 들어 hasOnebelongsTo

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

관계가 여러 개인 경우 : 예 : hasManybelongsToMany

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

4

이것이 Laravel 5에서 변경되었는지 확실 count($data->$relation)하지 않지만 관계 속성에 액세스하는 행위로 인해로드가 발생했기 때문에 허용 된 답변이 효과 가 없었습니다.

결국, 솔직히 isset($data->$relation)나를 위해 속임수를 썼습니다.


나는 그것이 $data->relation없는 것으로 생각합니다 $(6 글자 제한으로 인해 편집 할 수 없음)
Zanshin13

2
아, $relation당신과 같은 관계의 이름이 될 $data->posts것입니다. 혼란스러워서 죄송합니다 relation. 구체적인 모델 속성이 아님을 분명히 밝히고 싶었습니다 . : P
Dave Stewart

이것은 잠시 동안 작동했지만 Laravel을 5.2.29에서 5.2.45로 업데이트 한 후에 작동을 멈췄습니다. 왜 또는 어떻게 고쳐야할지 생각하십니까? 이제 어떤 이유로 관계형 데이터가로드됩니다.
Anthony

이 문제를 해결하는 답변을 추가했습니다.
Anthony

3

모델 객체 에서 relationLoaded 메서드를 사용할 수 있습니다 . 이것은 내 베이컨을 구해 주었기 때문에 다른 누군가에게 도움이되기를 바랍니다. 나는 한 이 제안을 주어 내가 Laracasts에 같은 질문을 할 때.


2

로 Hemerson 바렐라는 이미 PHP는 7.1에서 말했다 count(null)발생합니다 errorhasOne수익을 null더 행이 존재하지 않는 경우. hasOne관계 가 있기 때문에이 empty방법을 사용하여 확인합니다.

$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
   $option = $model->option;

   if(empty($option)){
      $option = $model->option()->create();
   }

   $option->someAttribute = temp;
   $option->save();
};

그러나 이것은 불필요한 것입니다. 관계가 존재하는지 확인 update하거나 create전화를 걸지 여부를 결정할 필요가 없습니다 . updateOrCreate 메소드를 사용하십시오 . 이것은 위와 같습니다.

$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {  
   $model->option()
         ->updateOrCreate(['repair_item_id' => $model->id],
                          ['option' => $temp]);
}

0

count ($ x) 함수의 사용이 잘못되어 PHP 버전을 7.2 이상으로 업데이트 할 때 코드를 완전히 리팩터링해야했습니다. 다른 시나리오에서 수백 가지 사용법이 있으며 모든 규칙에 맞는 규칙이 없기 때문에 이것은 정말 고통스럽고 매우 무섭습니다.

모든 것을 리팩토링하기 위해 따라야 할 규칙, 예 :

$ x = 인증 :: 사용자 ()-> 게시물-> 찾기 (6); (-> find ()를 사용하여 사용자가 게시물 id = 6을 가지고 있는지 확인)

[FAILS] if(count($x)) { return 'Found'; } 
[GOOD] if($x) { return 'Found'; }

$ x = 인증 :: 사용자 ()-> 프로필-> 부서; (프로필에 일부 부서가 있는지 확인하고 많은 부서가있을 수 있음)

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }

$ x = 인증 :: 사용자 ()-> 프로필-> get (); (-> get ()을 사용한 후 사용자에게 프로파일이 있는지 확인하십시오)

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }

질문이 제기 된 후 5 년이 지나면 이것이 도움이되기를 바랍니다.이 stackoverflow 게시물은 많은 도움이되었습니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.