Laravel开发学习笔记: 模型的关联查询

2021-02-1316:41:52后端程序开发Comments1,761 views字数 9080阅读模式

关联概念

关联模型,即:两张或以上的表进行一定规则的绑定关联。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

比如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

  • 一个学生(学生表)对应一张个人信息卡(信息表),这种就是一对一;
  • 一篇博文(帖子表)对应多个评论(评论表),这种就是一对多;
  • 一个用户(用户表)对应多个职位(权限表),而一个职位又可以有多个用户;那么,这种就是多对多关联;

当然,还有更多更复杂的关联,都是基于此的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

本文只探讨这三种基本的关联。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

既然是关联,当然会有绑定的概念,当有数据库操作,关联表也会跟着变动;这就是关联模型的意义。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

一对一关联

1、我们以下面的两张表为实例,进行演示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

Laravel开发学习笔记: 模型的关联查询文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

左侧users主表主键为id。在Laravel中,主键默认是id。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

右侧profiles附表,主键为id,外键为user_id。在laravel中,外键模式格式是主表名_主键文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

然后使用命令,创建两个表对应的模型model: 和文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

php artisan make:model Models/User
php artisan make:model Models/Profile

然后给两个表生成注释文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

php artisan ide-helper:models

2、正向关联:在主表中,写入关联附表的代码,格式及参数解释,如下所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionprofile(){return$this->hasOne(Profile::class,'user_id','id');}

然后,即可在控制类中使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$profiles= User::find(19)->profile;return$profiles;

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

{"id":1,"user_id":19,"hobby":"喜欢大姐姐","status":1}

在这个过程中,执行的SQL语句是两条,为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select*from`laravel_profiles`where`laravel_profiles`.`user_id`=19and`laravel_profiles`.`user_id`isnotnulllimit1

3、反向关联:在附表中,写入关联主表的代码,格式及参数如下所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionuser(){return$this->belongsTo(User::class,'user_id','id');}

然后可以在控制类中使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= Profile::find(1)->user;return$users;

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

{"id":19,"username":"蜡笔小新","password":"123","gender":"男",......}

在这个过程中,执行的SQL语句为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_profiles`where`laravel_profiles`.`id`=1limit1select*from`laravel_users`where`laravel_users`.`id`=19limit1

10.3 一对多关联

1、我们以下面的两张表进行演示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

Laravel开发学习笔记: 模型的关联查询文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

可以看出,这是一个一对多的关联。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

同样,为表books 创建模型:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

php artisan make:model Models/Book

并且生成注释:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

php artisan ide-helper:models

2、正向关联:在主表中,写入关联附表的代码,格式及参数解释,如下所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionbook(){return$this->hasMany(Book::class,'user_id','id');}

然后,即可在控制类中使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$books= User::find(19)->book;return$books;

执行结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":1,"user_id":19,"title":"《莎士比亚》"},{"id":10,"user_id":19,"title":"《热情天堂》"},{"id":11,"user_id":19,"title":"《完美人生》"},{"id":29,"user_id":19,"title":"《哈利波特》"}]

在这个过程中,执行的SQL语句是两条:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select*from`laravel_books`where`laravel_books`.`user_id`=19and`laravel_books`.`user_id`isnotnull

3、获取一对多关联的数据,如果再进行筛选,可以使用下面方法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$books= User::find(19)->book()->where('id',11)->get();return$books;

执行结果为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":11,"user_id":19,"title":"《完美人生》"}]

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select*from`laravel_books`where`laravel_books`.`user_id`=19and`laravel_books`.`user_id`isnotnulland`id`=11

4、反向关联:在附表中,写入关联主表的代码。和一对一的反向关联一致。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionuser(){return$this->belongsTo(User::class,'user_id','id');}

然后在控制类中执行代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= Book::find(1)->user;return$users;

执行结果为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

{"id":19,"username":"蜡笔小新","password":"123","gender":"男",......}

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_books`where`laravel_books`.`id`=1limit1select*from`laravel_users`where`laravel_users`.`id`=19limit1

10.4 多对多关联

1、多对多关联,比前面两种要复杂一些,需要一张中间表,共三张;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

我们以下面的 3 张表进行演示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

Laravel开发学习笔记: 模型的关联查询文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

左表:.users:用户表文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

中表:.role_users:中间表,默认表名是这样的。然后两边互相关联的默认外键:user_id,role_id。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

右表:.roles:权限表文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

对于这三张表,只需要创建用户表权限表的模型即可:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

php artisan make:model Models/User
php artisan make:model Models/Role

同样,写入注释:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

php artisan ide-helper:models

2、正向关联:在 设置多对多关联文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionrole(){return$this->belongsToMany(Role::class,'role_users','user_id','role_id');}

留空。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

然后即可在控制类中使用。比如多对多的关联输出:查看用户19都拥有哪些权限文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$roles= User::find(19)->role;return$roles;

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":2,"type":"评论审核专员","pivot":{"user_id":19,"role_id":2}},{"id":3,"type":"图片监察员","pivot":{"user_id":19,"role_id":3}},{"id":1,"type":"超级管理员","pivot":{"user_id":19,"role_id":1}}]

多对多会生成一个中间字段:pivot,里面包含多对多的双id;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select`laravel_roles`.*,`laravel_role_users`.`user_id`as`pivot_user_id`,`laravel_role_users`.`role_id`as`pivot_role_id`from`laravel_roles`innerjoin`laravel_role_users`on`laravel_roles`.`id`=`laravel_role_users`.`role_id`where`laravel_role_users`.`user_id`=19

3、获取权限列表中某一个数据,和一对多操作方法一样,但注意返回的表名称;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$roles= User::find(19)->role()->where('role_id',1)->get();return$roles;$roles= User::find(19)->role;return$roles->where('id',1);

执行结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":1,"type":"超级管理员","pivot":{"user_id":19,"role_id":1}}]

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select`laravel_roles`.*,`laravel_role_users`.`user_id`as`pivot_user_id`,`laravel_role_users`.`role_id`as`pivot_role_id`from`laravel_roles`innerjoin`laravel_role_users`on`laravel_roles`.`id`=`laravel_role_users`.`role_id`where`laravel_role_users`.`user_id`=19and`role_id`=1

4、反向关联:多对多的反向关联和其它两种方式也差不多,在模型中:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionuser(){return$this->belongsToMany(User::class,'role_users','role_id','user_id');}

然后在控制类中执行:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= Role::find(1)->user;return$users;

执行结果如下,即查询拥有权限1(超级管理员)的用户:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":24,"username":"小明","password":"123",......"pivot":{"role_id":1,"user_id":24}},{"id":19,"username":"蜡笔小新","password":"123",......"pivot":{"role_id":1,"user_id":19}},{"id":99,"username":"辉夜","password":"123",......"pivot":{"role_id":1,"user_id":99}}]

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_roles`where`laravel_roles`.`id`=1limit1select`laravel_users`.*,`laravel_role_users`.`role_id`as`pivot_role_id`,`laravel_role_users`.`user_id`as`pivot_user_id`from`laravel_users`innerjoin`laravel_role_users`on`laravel_users`.`id`=`laravel_role_users`.`user_id`where`laravel_role_users`.`role_id`=1

5、多对多会生成一个中间字段:pivot,里面包含多对多的双id文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

如果想要pivot 字段包含更多的中间表字段,可以自行添加,还可以修改字段名。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

比如正向关联中,修改为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionrole(){return$this->belongsToMany(Role::class,'role_users','user_id','role_id')->withPivot('details','id')->as('pivot_name');}

然后执行:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$roles= User::find(19)->role()->where('role_id',1)->get();return$roles;

执行结果为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":1,"type":"超级管理员","pivot_name":{"user_id":19,"role_id":1,"details":"啦","id":8}}]

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select`laravel_roles`.*,`laravel_role_users`.`user_id`as`pivot_user_id`,`laravel_role_users`.`role_id`as`pivot_role_id`,`laravel_role_users`.`details`as`pivot_details`,`laravel_role_users`.`id`as`pivot_id`from`laravel_roles`innerjoin`laravel_role_users`on`laravel_roles`.`id`=`laravel_role_users`.`role_id`where`laravel_role_users`.`user_id`=19and`role_id`=1

6、定义多对多绑定时,可以在绑定方法内筛选数据;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

比如正向关联中,修改为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

publicfunctionrole(){return$this->belongsToMany(Role::class,'role_users','user_id','role_id')->wherePivot('id',1);}

还有wherePivotIn,以及派生的四种方法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

然后执行:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$roles= User::find(19)->role;return$roles;

输出结果为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":2,"type":"评论审核专员","pivot":{"user_id":19,"role_id":2}}]

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select`laravel_roles`.*,`laravel_role_users`.`user_id`as`pivot_user_id`,`laravel_role_users`.`role_id`as`pivot_role_id`from`laravel_roles`innerjoin`laravel_role_users`on`laravel_roles`.`id`=`laravel_role_users`.`role_id`where`laravel_role_users`.`user_id`=19and`laravel_role_users`.`id`=1

除了一对一,一对多,多对多,还有派生的远程一对一,远程一对多,以及多态一对一,多态一对多,多态多对多。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

关联查询

前文讲述了三种常用的关联查询。本节讲述几种常用查询方案。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

1、下面两种查询方式是一样的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$books= User::find(19)->book;$books= User::find(19)->book()->get();

2、可以采用where 筛选或闭包。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

books = User::find(19)->book()->where('id',1)->orWhere('id',11)->get();$books= User::find(19)->book()->where(function($query){$query->where('id',1)->orWhere('id',11);})->get();

执行结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":1,"user_id":19,"title":"《莎士比亚》"},{"id":11,"user_id":19,"title":"《完美人生》"}]

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`where`laravel_users`.`id`=19limit1select*from`laravel_books`where`laravel_books`.`user_id`=19and`laravel_books`.`user_id`isnotnulland`id`=1or`id`=11

3、使用has()方法,可以查询某些条件下的关联查询数据。如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= User::has('book')->get();return$users;$users= User::has('book','>=',3)->get();return$users;

执行的SQL分别为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`whereexists(select*from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`)select*from`laravel_users`where(selectcount(*)from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`)>=3

执行结果分别为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

[{"id":19,"username":"蜡笔小新","password":"123",......},{"id":20,"username":"路飞","password":"123",......},{"id":21,"username":"黑崎一护","password":"456",......},{"id":24,"username":"小明","password":"123",......},{"id":25,"username":"孙悟饭","password":"123",......},......][{"id":19,"username":"蜡笔小新","password":"123",......}]

4、使用whereHas()方法,创建闭包查询;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= User::whereHas('book',function($query){$query->where('id',2);})->get();return$users;

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`whereexists(select*from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`and`id`=2)

5、使用doesntHave()方法,即has()的反向操作:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= User::doesntHave('book')->get();return$users;

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select*from`laravel_users`wherenotexists(select*from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`)

6、使用withCount()方法,可以进行关联统计;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= User::withCount('book')->get();return$users;

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select`laravel_users`.*,(selectcount(*)from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`)as`book_count`from`laravel_users`

再如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= User::withCount(['profile','book'])->get();return$users;

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select`laravel_users`.*,(selectcount(*)from`laravel_profiles`where`laravel_users`.`id`=`laravel_profiles`.`user_id`)as`profile_count`,(selectcount(*)from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`)as`book_count`from`laravel_users`

再如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

$users= User::withCount(['profile','book'=>function($query){$query->where('user_id',19);}])->get();return$users;

执行的SQL为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

select`laravel_users`.*,(selectcount(*)from`laravel_profiles`where`laravel_users`.`id`=`laravel_profiles`.`user_id`)as`profile_count`,(selectcount(*)from`laravel_books`where`laravel_users`.`id`=`laravel_books`.`user_id`and`user_id`=19)as`book_count`from`laravel_users`

以上。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/20946.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/20946.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定