新入职后组长安排了一个小的管理项目来检验能力,后发现自身对于 ThinkPHP 框架中的模型关联属于一窍不通,故被终止项目叫楼主去恶补 ThinkPHP6 框架知识。
对于多联表查询之前本人一直使用join方法,但是此方法对于代码效率和维护都有较大影响,故在此尝试使用 ThinkPHP 框架内置的模型关联来对多联表进行操作(本次只记录查询操作)
一、建立数据表
首先我们先创建三个简易的数据表 User、Article、Comment 并添加一些测试数据,结构如下:
User:
Article:
Comment:
其中 Article 表使用 user_id 与 User 表关联;Comment 表使用 article_id 与 Article 表进行关联。接下来我们来设置对应的数据库模型代码。
二、建立对应数据表模型,并添加关联
在 User 模型中,我们想实现根据提供的用户 ID 查询出该用户对应的所有文章以及这些文章对应的评论
class User extends Model
{
//主键
protected $pk = 'user_id';
//关联文章
public function articles(){
return $this->hasMany(Article::class, 'user_id', 'user_id');
}
//根据文章关联评论
public function comments(){
return $this->hasManyThrough(Comment::class, Article::class, 'user_id', 'article_id', 'user_id', 'article_id');
}
}
由于 User 表与 Comment 表没有直接的对应关系,所以我们使用 hasManyThrough()
方法来建立远程模型关联。其中 Comment 是我们要关联的目标模型;Article 是中间模型;第一个 user_id 是中间模型外键,第二个 article_id 是中间模型与目标模型关联键,第三个 user_id 是当前模型的主键,第四个 article_id 是中间模型的主键。
接下来我们来设置 Article 模型的关联关系,要求实现根据提供的 ID 查询出该文章与所对应的所有评论
class Article extends Model
{
//主键
protected $pk = 'article_id';
//关联用户
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'user_id');
}
//一对多关联评论
public function comments()
{
return $this->hasMany(Comment::class, 'article_id', 'article_id');
}
}
最后我们还需要设置 Comment 模型
class Comment extends Model
{
//主键
protected $pk = 'comment_id';
//关联文章
public function article()
{
return $this->belongsTo(Article::class, 'article_id', 'article_id');
}
}
三、编写控制器关联查询代码
由于是演示代码,所以暂时都在 index 控制器下编写、同时我们默认所有的路由表已经配好
首先,我们来实现一个给出任意文章 ID 我们返回此 ID 的文章信息同时返回该文章的所有评论的功能
public function article($id)
{
$article = Article::with(['comments'])->find($id);
return json_encode($article);
}
其中 with(['comments'])
对应我们在 Article 模型中创建的关联方法,之后我们用 17 号文章请求这个接口,会得到如下数据:
{
"article_id":17,
"user_id":1,
"title":"test2",
"status":0,
"comments":[
{"comment_id":9,"article_id":17,"comment":"test comment 1","status":1},
{"comment_id":10,"article_id":17,"comment":"test comment 2","status":1},
{"comment_id":11,"article_id":17,"comment":"test comment 3","status":1}]
}
可以看到此时模型返回了 17 号文章信息与该文章下所有的评论信息。至此我们完成了一个一对多的双表关联查询
接下来我们尝试实现根据给出的用户 ID 返回该用户对应的所有文章以及这些文章所对应的所有评论
public function user($id)
{
$user = User::with(['articles' =>function($query){
$query->with(['comments']);
}])->find($id);
return json_encode($user);
}
此时我们先使用 with(['articles'])
关联 Article 表来查询文章,之后在 with()
方法内使用闭包来使 Comment 表与 Article 表进行关联,这样可以使查询到的评论与文章之间是父子结构;接下来我们使用 2 号用户请求这个接口,会得到如下数据:
{
"user_id":2,
"username":"test",
"password":"123456",
"articles":[
{"article_id":14,"user_id":2,"title":"test2","status":1,"comments":[]},
{"article_id":15,"user_id":2,"title":"test3","status":1,"comments":[]},
{"article_id":16,"user_id":2,"title":"test1","status":1,"comments":[
{"comment_id":6,"article_id":16,"comment":"test comment 1","status":1},
{"comment_id":7,"article_id":16,"comment":"test comment 2","status":1},
{"comment_id":8,"article_id":16,"comment":"test comment 3","status":1}]},
{"article_id":19,"user_id":2,"title":"test1","status":1,"comments":[
{"comment_id":17,"article_id":19,"comment":"test comment 1","status":1},
{"comment_id":18,"article_id":19,"comment":"test comment 2","status":1},
{"comment_id":19,"article_id":19,"comment":"test comment 3","status":1}]},
{"article_id":20,"user_id":2,"title":"test2","status":1,"comments":[
{"comment_id":20,"article_id":20,"comment":"test comment 1","status":1},
{"comment_id":21,"article_id":20,"comment":"test comment 2","status":1},
{"comment_id":22,"article_id":20,"comment":"test comment 3","status":1}]},
{"article_id":21,"user_id":2,"title":"test3","status":1,"comments":[
{"comment_id":23,"article_id":21,"comment":"test comment 1","status":1},
{"comment_id":24,"article_id":21,"comment":"test comment 2","status":1},
{"comment_id":25,"article_id":21,"comment":"test comment 3","status":1}]}]
}
可以看到这样直接查询出了所有与用户对应的文章以及这些文章所对应评论,同时表与表之间的数据是有父子关系的。
而当我们不使用闭包函数,而是直接在 with()
方法内直接调用我们在 User 模型中定义的远程关联 Comment 会返回什么样的数据呢?此时我们修改一下控制器中的代码
$user = User::with(['articles', 'comments'])->find($id);\\删除语句中的闭包
此时我们再次拿同样的 ID 请求这个接口,会得到如下数据:
{
"user_id":2,
"username":"test",
"password":"123456",
"articles":[
{"article_id":14,"user_id":2,"title":"test2","status":1},
{"article_id":15,"user_id":2,"title":"test3","status":1},
{"article_id":16,"user_id":2,"title":"test1","status":1},
{"article_id":19,"user_id":2,"title":"test1","status":1},
{"article_id":20,"user_id":2,"title":"test2","status":1},
{"article_id":21,"user_id":2,"title":"test3","status":1}],
"comments":[
{"comment_id":6,"article_id":16,"comment":"test comment 1","status":1},
{"comment_id":7,"article_id":16,"comment":"test comment 2","status":1},
{"comment_id":8,"article_id":16,"comment":"test comment 3","status":1},
{"comment_id":17,"article_id":19,"comment":"test comment 1","status":1},
{"comment_id":18,"article_id":19,"comment":"test comment 2","status":1},
{"comment_id":19,"article_id":19,"comment":"test comment 3","status":1},
{"comment_id":20,"article_id":20,"comment":"test comment 1","status":1},
{"comment_id":21,"article_id":20,"comment":"test comment 2","status":1},
{"comment_id":22,"article_id":20,"comment":"test comment 3","status":1},
{"comment_id":23,"article_id":21,"comment":"test comment 1","status":1},
{"comment_id":24,"article_id":21,"comment":"test comment 2","status":1},
{"comment_id":25,"article_id":21,"comment":"test comment 3","status":1}]
}
可以看到虽然也都查询出了所有数据,但是文章与评论之间并不是父子关系而是同级关系。
至此双表与三表的多表之间模型关联查询的代码已经介绍演示完毕,具体的应用场景需要读者们根据自身的业务场景来具体处理;本文章仅代表个人的学习经验,具体代码与参数设置请参考ThinkPHP官方开发文档。
第一次写博客记录学习过程,如有错误还请大佬们多多指出。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容