Laravel-Eloquent "Has", "With", "WhereHas"-무슨 뜻입니까?


답변:


555

with()위한 열망로드 . 기본적으로 라 라벨은 사용자가 지정한 관계를 미리로드한다는 의미입니다. 모델 모음이 있고 모든 모델에 대한 관계를로드하려는 경우 특히 유용합니다. 로딩이 열리기 때문에 컬렉션의 모든 모델에 대해 하나가 아닌 하나의 추가 DB 쿼리 만 실행하기 때문입니다.

예:

User > hasMany > Post

$users = User::with('posts')->get();
foreach($users as $user){
    $users->posts; // posts is already loaded and no additional DB query is run
}

있다

has()관계에 따라 선택 모델을 필터링하는 것입니다. 따라서 일반적인 WHERE 조건과 매우 유사하게 작동합니다. 그냥 사용 has('relation')하면이 관계에서 하나 이상의 관련 모델이있는 모델 만 가져 오기를 의미합니다.

예:

User > hasMany > Post

$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection

어디에

whereHas()기본적으로 동일하게 작동 has()하지만 관련 모델에서 확인할 추가 필터를 지정할 수 있습니다.

예:

User > hasMany > Post

$users = User::whereHas('posts', function($q){
    $q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned

101
+1, 매우 유용한 답변입니다! 반면이 있음을 유의하십시오 with('relation')반환 된 컬렉션의 관련 테이블의 데이터가 포함됩니다, has('relation')그리고 whereHas('relation')없는 관련 테이블의 데이터가 포함됩니다. 당신은 모두를 호출 할 필요가 있습니다 그래서 with('relation')뿐만 아니라 has()whereHas().
Soulriser

1
답변, 관계 모델에서 상위 모델에 액세스하는 방법 예를 들어 여기에서 사용자 모델의 속성을 기반으로 게시물 모델을 검색하는 방법
hussainfrotan

@BhojendraNepal 불행히도 문서에는 그다지 많지 않은 것 같습니다 ... 이것이 내가 찾은 전부입니다 (몇 개의 단락이 있습니다)
lukasgeiter

@ Hussainfrotan 같은 방식으로 whereHas게시물을 쿼리 할 때 사용자 관계에 사용하십시오.
Michael Tsang

Laravel 설명서, 호기심 : laravel.com/docs/5.8/eloquent-relationships 사용하는 경우, whereHas그것을 사용하는 use Illuminate\Database\Eloquent\Builder;다음과입니다 function(Builder $query). 내가 본 대부분의 예제는 dot을 사용 Builder하고 $ query를 전달하면 올바른 방법입니까?
Guntar

8

문서 에서 이미 사용법을 설명했습니다. 그래서 나는이 방법들을 설명하기 위해 SQL을 사용하고 있습니다.

예:


Order (orders)많은 것이 있다고 가정합니다 OrderItem (order_items).

그리고 당신은 이미 그들 사이의 관계를 구축했습니다.

// App\Models\Order:
public function orderItems() {
    return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}

이 세 가지 방법은 모두 관계를 기반으로합니다 .


결과 : with() 모델 객체와 관련 결과를 반환합니다.

장점 : 그것은이다 열망 로딩 할 수 N + 1 문제를 방지 .

다음 Eloquent Builder를 사용하는 경우 :

Order::with('orderItems')->get();

라 라벨은이 코드를 두 개의 SQL로만 변경합니다 :

// get all orders:
SELECT * FROM orders; 

// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);

그리고 laravel 은 외래 키에 의한 첫 번째 SQL의 결과 와 다른 두 번째 SQL의 결과를 병합 합니다 . 마지막으로 수집 결과를 반환합니다.

따라서 foreign_key가없는 열을 선택하면 관계 결과가 비어 있습니다.

Order::with(['orderItems' => function($query) { 
           // $query->sum('quantity');
           $query->select('quantity'); // without `order_id`
       }
])->get();

#=> result:
[{  id: 1,
    code: '00001',
    orderItems: [],    // <== is empty
  },{
    id: 2,
    code: '00002',
    orderItems: [],    // <== is empty
  }...
}]

있다


Has관계가 비어 있지 않은 모델의 객체를 반환합니다 .

Order::has('orderItems')->get();

라 라벨은이 코드를 하나의 SQL로 변경합니다 :

select * from `orders` where exists (
    select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)

어디에


whereHasorWhereHas방법을 넣어 where당신에 조건을 has쿼리. 이 메소드를 사용하면 사용자 정의 제한 조건을 관계 제한 조건에 추가 할 수 있습니다 .

Order::whereHas('orderItems', function($query) {
   $query->where('status', 1);
})->get();

라 라벨은이 코드를 하나의 SQL로 변경합니다 :

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.