Laravel-雄辩的“有”,“有”,“在哪里”-它们是什么意思?


Answers:


553

with()渴望加载。这基本上意味着,沿着主模型,Laravel将预加载您指定的关系。如果您有一组模型并且要为所有模型加载关系,则这特别有用。因为急切加载,您只运行一个附加的数据库查询,而不是集合中每个模型的查询。

例:

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,非常有帮助的答案!还要注意,while with('relation')将在返回的集合中包含相关表的数据,has('relation')并且whereHas('relation')包含相关表的数据。因此,您可能需要同时调用with('relation')has()whereHas()
Soulriser '16

1
问候,如何从关系模型访问父模型,例如此处如何基于用户模型的属性搜索帖子模型
hussainfrotan

@BhojendraNepal不幸的是,在文档中似乎没有太多关于此的内容…… 这就是我发现的所有内容(以下几段)
lukasgeiter

@hussainfrotan相同,whereHas在查询帖子时用于用户关系。
曾荫权'18

奇怪的是,在Laravel文档中:laravel.com/docs/5.8/eloquent-relationships,使用whereHas时使用use Illuminate\Database\Eloquent\Builder;,然后使用function(Builder $query)。我看到的大多数示例都使用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();

Laravel将此代码更改为仅两个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将此代码更改为一个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将此代码更改为一个SQL

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.