Laravel-雄弁な「Has」、「With」、「WhereHas」-どういう意味ですか?


回答:


553

with()以下のためである積極的なロード。つまり、基本的に、メインモデルに沿って、Laravelは指定した関係をプリロードします。これは、モデルのコレクションがあり、すべてのモデルのリレーションをロードする場合に特に役立ちます。積極的なロードでは、コレクション内のすべてのモデルに対して1つではなく、1つの追加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')する場合は、この関係に少なくとも1つの関連モデルがあるモデルのみを取得することを意味します。

例:

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 2016

1
挨拶、たとえばリレーションモデルから親モデルにアクセスする方法ここでは、ユーザーモデルの属性に基づいて投稿モデルを検索する方法
hussainfrotan

@BhojendraNepal残念ながら、ドキュメントにはそれほど多くはないようです... これは私が見つけたすべてです(数
段落下にあります

@hussainfrotanと同じ方法で、whereHas投稿をクエリするときにユーザー関係で使用します。
Michael Tsang

Laravelのドキュメントで、好奇心が強い:laravel.com/docs/5.8/eloquent-relationships使用した場合、whereHasそれを用途use Illuminate\Database\Eloquent\Builder;その後ですfunction(Builder $query)。私が見たほとんどの例、ドットはを使用Builderし、$ queryを渡すだけです。これは正しい方法ですか?
ガンター

8

ドキュメントはすでに使用法を説明しています。だから私はこれらの方法を説明するためにSQLを使用しています

例:


があると仮定すると、Order (orders)多くがありOrderItem (order_items)ます。

そして、あなたはすでにそれらの間の関係を構築しています。

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

これら3つの方法はすべて、関係に基づいています。


結果: with()モデルオブジェクトとその関連結果を返します。

利点:それは熱心ローディングできるN + 1つの問題を防ぎます

次のEloquent Builderを使用している場合:

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

Laravelはこのコードを2つの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();

Laravelはこのコードを1つのSQLに変更します

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

どこ


whereHasそして、orWhereHas置く方法whereあなたの上の条件をhasクエリ。これらのメソッドを使用すると、カスタマイズされた制約を関係制約に追加できます

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

Laravelはこのコードを1つの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.