这句查询 with ('user') 是如何用到的查询的就是微博数据为什么和 user 表有关系??求大神详细解答。

return Status::whereIn('user_id', $user_ids)
->with('user')
->orderBy('created_at', 'desc');

桃知夭夭
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
KayuHo
最佳答案

定义了关联就可以取出关联的数据了,用 with() 是为了预加载,避免 N+1 查询问题。
文档

6年前 评论
讨论数量: 12
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Status extends Model
{
    protected $fillable = ['content'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
6年前 评论
KayuHo

定义了关联就可以取出关联的数据了,用 with() 是为了预加载,避免 N+1 查询问题。
文档

6年前 评论

@Joy_he 不是很理解 文档我也看过了, Status::whereIn('user_id', $user_ids) user_ids已经有了 然后查询 微博列表 为什么还去关联一下users 表 在我看来来 就是单表查询啊~~~

6年前 评论

@AmberLavigne 因为要显示用户的名字,头像呀,不用with的话只有user_id字段,还得自己去关联

6年前 评论

@GerBawn

  1. 这里with('user')的功能应该只有一个,就是教程与文档中说的预加载,减少查询次数,提高代码执行效率.
    你完全可以删掉这句试试,程序会正常运行.
  2. 并不是说不用with的话只有user_id字段
    视图_feed.blade.php第四行中结尾处的$status->user是用户数据的调用处.它会调用模型Status中的user方法.用户数据是这么来的.
6年前 评论

@AmberLavigne 因为在file需要关联查询动态对应的用户信息,所以前面做了with预加载

6年前 评论

这里面的with绝对是多余的。我把非with的和有with的方式都打印出来了。

打印出的数组为

with后:

[0] => Array
    (
        [query] => select * from `users` where `id` = ? limit 1
        [bindings] => Array
            (
                [0] => 105
            )

        [time] => 11.1
    )

[1] => Array
    (
        [query] => select `users`.*, `followers`.`follower_id` as `pivot_follower_id`, `followers`.`user_id` as `pivot_user_id` from `users` inner join `followers` on `users`.`id` = `followers`.`user_id` where `followers`.`follower_id` = ?
        [bindings] => Array
            (
                [0] => 105
            )

        [time] => 0.43
    )

[2] => Array
    (
        [query] => select count(*) as aggregate from `statuses` where `user_id` in (?, ?, ?, ?)
        [bindings] => Array
            (
                [0] => 101
                [1] => 102
                [2] => 3
                [3] => 105
            )

        [time] => 0.49
    )

[3] => Array
    (
        [query] => select * from `statuses` where `user_id` in (?, ?, ?, ?) order by `created_at` desc limit 30 offset 120
        [bindings] => Array
            (
                [0] => 101
                [1] => 102
                [2] => 3
                [3] => 105
            )

        [time] => 1.3
    )

[4] => Array
    (
        [query] => select * from `users` where `users`.`id` in (?, ?, ?)
        [bindings] => Array
            (
                [0] => 101
                [1] => 102
                [2] => 105
            )

        [time] => 0.32
    )

非with:

[0] => Array
    (
        [query] => select * from `users` where `id` = ? limit 1
        [bindings] => Array
            (
                [0] => 105
            )

        [time] => 10.52
    )

[1] => Array
    (
        [query] => select `users`.*, `followers`.`follower_id` as `pivot_follower_id`, `followers`.`user_id` as `pivot_user_id` from `users` inner join `followers` on `users`.`id` = `followers`.`user_id` where `followers`.`follower_id` = ?
        [bindings] => Array
            (
                [0] => 105
            )

        [time] => 0.34
    )

[2] => Array
    (
        [query] => select count(*) as aggregate from `statuses` where `user_id` in (?, ?, ?, ?)
        [bindings] => Array
            (
                [0] => 101
                [1] => 102
                [2] => 3
                [3] => 105
            )

        [time] => 0.28
    )

[3] => Array
    (
        [query] => select * from `statuses` where `user_id` in (?, ?, ?, ?) order by `created_at` desc limit 30 offset 120
        [bindings] => Array
            (
                [0] => 101
                [1] => 102
                [2] => 3
                [3] => 105
            )

        [time] => 1.3
    )

这里证明非with照样可以取出用户数据而且少了一条sql,作者能帮忙解释下么

5年前 评论

@rambo 因为使用with避免了N+1问题,虽然输出结果一样,但数据库查询次数不一样。

5年前 评论

@rambo 开启debug ,然后在里面看下SQL 查询,再去对比下SQL条数,你就明白了

5年前 评论

来拆解一下教程中的查询语句

假设 user_ids = [1,2,3]并且status表中有100条数据

Status::whereIn('user_id', $user_ids)->orderBy('created_at','desc');

如果不带with('user'),最终执行的sql语句如下

select * from `statuses` where `user_id` in (1, 2, 3) order by `created_at` desc

这个时候,我们来循环打印出所有status关联的user的id

$user_ids = [1,2,3];
$statuses = Status::whereIn('user_id', $user_ids)->orderBy('created_at','desc')->get();
foreach($statuses as $status)
  {
     echo $status->user->id;
  }

由于在status模型中定义的user方法,这时候会向数据库提交请求,查询users表,最终执行的sql代码如下

select * from `users` where `users`.`id` = 1 limit 1
select * from `users` where `users`.`id` = 3 limit 1 
select * from `users` where `users`.`id` = 2 limit 1
.
.
.
select * from `users` where `users`.`id` = 1 limit 1
select * from `users` where `users`.`id` = 3 limit 1 
select * from `users` where `users`.`id` = 2 limit 1

总计执行了101次


再次加上with('user')查询看一下

Status::whereIn('user_id', $user_ids)->with('user')->orderBy('created_at','desc');

最终执行的sql语句如下

select * from `statuses` where `user_id` in (1, 2, 3) order by `created_at` desc
select * from `users` where `users`.`id` in (1, 2, 3)

在查询status表的同时,也查询出了 users表中的所有user_ids关联的数据

再次循环打印出所有status关联的user的id

foreach($statuses as $status)
  {
     echo $status->user->id;
  }

最终执行的sql语句如下

select * from `statuses` where `user_id` in (1, 2, 3) order by `created_at` desc
select * from `users` where `users`.`id` in (1, 2, 3)

发现sql语句没有变化,并没有向数据库查询,因为status关联的user字段已经被查询出来了

这里之所以使用with关联,是因为视图中也使用了status->user方法,可以想象,如果没有使用with('user')关联同时查询出users表中的相关用户,最终的sql查询是多么可怕。

3年前 评论

用with(user),就是把Status对应的所有user对象一次性从数据库取出来读进内存里。 然后需要用user的某些字段的时候,直接从内存读,不需要再查询数据库。

我是这么理解的不知道对不对。

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!