ChatGPT解决这个技术问题 Extra ChatGPT

Laravel - 雄辩的“Has”、“With”、“WhereHas”——它们是什么意思?

我发现这些方法背后的概念和含义有点令人困惑,有人可以在示例的上下文中向我解释 haswith 之间的区别(如果可能的话)吗?

另请参阅 stackoverflow.com/Laravel "scope" query inside join?

C
Cato Minor

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

+1,非常有帮助的答案!另请注意,虽然 with('relation') 将在返回的集合中包含相关表的数据,但 has('relation')whereHas('relation')包含相关表的数据。因此,您可能需要同时调用 with('relation') 以及 has()whereHas()
问候答案,如何从关系模型访问父模型,例如这里如何根据用户模型的属性搜索帖子模型
@BhojendraNepal 不幸的是,文档中似乎没有太多关于它的内容...... This is all I found(下面几段)
@hussainfrotan 以同样的方式,在查询帖子时对用户关系使用 whereHas
奇怪的是,在 Laravel 文档中: laravel.com/docs/5.8/eloquent-relationships ,当使用 whereHas 时,它使用 use Illuminate\Database\Eloquent\Builder;,然后是 function(Builder $query)。我看到的大多数示例,点使用 Builder,只需传入 $query,这是正确的方法吗?
C
Community

documentation已经解释了用法,所以我将使用SQL来解释方法。

例子:

假设有一个 Order (orders) 有许多 OrderItem (order_items) 并且您已经建立了它们之间的关系:

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

这三种方法都是基于关系的。

结果: with() 返回模型对象及其相关结果。

优点:是eager-loading,可以防止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 `orders`.`id` = `order_items`.`order_id`
)

哪里有

方法 whereHasorWhereHas 为您的 has 查询设置了 where 条件。这些方法允许您将自定义约束添加到关系约束

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
)