ThinkPHP一对多的关联模型运用

news2024/11/17 6:57:06

一、序言

最近在写ThinkPHP关联模型的时候一些用法总忘,我就想通过写博客的方式复习和整理下一些用法。

具体版本:

  • topthink/framework:6.1.4
  • topthink/think-orm:2.0.61

二、实例应用

1、一对多的关联

本文案例:一个用户对应多篇文章,一篇文章对应多条评论。

以下是用户、文章、评论的模型建立:

(1)用户模型

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/19
 * Time: 14:50
 */

namespace app\common\model;

/**
 * 用户模型
 */
class UserModel extends ComBaseModel
{
    protected $name='user';

    /**
     * 文章关联表:一对多
     * hasMany()
     * 第一个参数:要关联的模型类
     * 第二个参数:在关联表中表示当前模型的外键名
     * 第三个参数:当前模型(userModel)的主键名
     * @return \think\model\relation\HasMany
     * @Author: fengzi
     * @Date: 2024/7/3 11:40
     */
    public function article()
    {
        return $this->hasMany(ArticleModel::class,'user_id','id');
    }

    /**
     * 评论表模型:远程一对多关联
     * hasManyThrough()
     * 第一个参数(必须):关联的模型类
     * 第二个参数(必须):中间表的模型类
     * 第三个参数:在中间模型中表示当前模型的外键
     * 第四个参数:在关联模型中表示当前模型的外键
     * 第五个参数:当前模型主键
     * 第六个参数:中间模型主键
     * @return \think\model\relation\HasManyThrough
     * @Author: fengzi
     * @Date: 2024/7/3 11:42
     */
    public function articleComment()
    {
        return $this->hasManyThrough(ArticleCommentModel::class, ArticleModel::class, 'user_id', 'user_id', 'id', 'id');
    }
}

(2)文章模型

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/19
 * Time: 14:50
 */

namespace app\common\model;

/**
 * 文章模型
 */
class ArticleModel extends ComBaseModel
{
    protected $name='article';

    /**
     * 用户模型
     * belongsTo()
     * 第一个参数:关联模型类
     * 第二个参数:在当前模型(ArticleModel)中表示关联模型(UserModel)的外键
     * 第三个参数:关联模型主键
     * @return \think\model\relation\BelongsTo
     * @Author: fengzi
     * @Date: 2024/7/3 13:54
     */
    public function user()
    {
        return $this->belongsTo(UserModel::class, 'user_id', 'id');
    }

    /**
     * 评论关联表:一对多
     * hasMany()
     * 第一个参数:要关联的模型类
     * 第二个参数:在关联表中表示当前模型的外键名
     * 第三个参数:当前模型(ArticleModel)的主键名
     * @return \think\model\relation\HasMany
     * @Author: fengzi
     * @Date: 2024/7/3 11:40
     */
    public function comment()
    {
        return $this->hasMany(ArticleCommentModel::class, 'article_id', 'id');
    }

}

(3)评论模型

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/19
 * Time: 14:50
 */

namespace app\common\model;

/**
 * 文章评论模型
 */
class ArticleCommentModel extends ComBaseModel
{
    protected $name='article_comment';

    /**
     * 评论模型
     * belongsTo()
     * 第一个参数:关联模型类
     * 第二个参数:在当前模型(ArticleCommentModel)中表示关联模型(ArticleModel)的外键
     * 第三个参数:关联模型主键
     * @return \think\model\relation\BelongsTo
     * @Author: fengzi
     * @Date: 2024/7/3 13:54
     */
    public function article()
    {
        return $this->belongsTo(ArticleModel::class, 'article_id', 'id');
    }

}

2、一对多查询:

(1)一对多的简单查询示例

public function many()
{
    // 实例化模型
    $userModel = app(UserModel::class);
    $articleModel = app(ArticleModel::class);
    $articleCommentModel = app(ArticleCommentModel::class);

    /** 关联查询 */
    // 查询ID=1的用户
    $user = $userModel->find(1);
    dump($user->toArray());
    // 查询ID=1的用户的所有文章,【article()】就是UserModel模型中定义的关联方法
    $article = $user->article()->select()->toArray();
    dump($article);

    /** 根据关联条件查询 */
    // 查询评论大于等于4个的文章,【comment】就是ArticleModel模型中定义的【comment()】关联方法
    $lists = $articleModel->has('comment','>=',4)->select()->toArray();
    dump($lists);

    // 查询评论评论来源为APP的文章(评论来源source:1web,2App),【comment】就是ArticleModel模型中定义的【comment()】关联方法
    $lists = $articleModel->hasWhere('comment',['source'=>2])->select()->toArray();
    dump($lists);

    /** 复杂的关联条件查询 */
    // 当有复杂的查询条件时,可以先通过评论表进行查询,把查询结果的对象当作条件,再关联文章表
    // 不需要select()或find()方法进行查询,直接返回查询对象即可
    $articleCommentWhere = $articleCommentModel->where([['source', '=', 2], ['content', 'like', '%有点耐%'], ['user_id', '=', 1]]);
    // 【comment】就是ArticleModel模型中定义的【comment()】关联方法
    $lists = $articleModel->hasWhere('comment', $articleCommentWhere)->select()->toArray();
    dd($lists);
}

(2)一对多的预查询加载

  • 一对多关联查询的时候只能用【with()】,不能用【withJion()】。
  • 当用户模型(UserModel)中关联文章变成一对一的时候【return $this->hasOne(ArticleModel::class,'user_id','id');】,【with()】和【withJion()】两个都可以使用。但需注意以下几点:
    • 使用with()的时候,关联数据可以正常输出,withCount()等方法可以同时使用。
    • 使用withJoin()的时候,关联数据可以正常输出,但withCount()等方法不可以同时使用。
  • withCount()、withSum()、withAvg()、withMax()等类似的方法所输出的字段格式为:关联名称(article)+ “_” + [count | sum | avg | max]。例如:article_count
public function many()
{
    // 实例化模型
    $userModel = app(UserModel::class);

    // 查询ID=1的用户,关联查询文章,【article】就是UserModel模型中定义的关联方法
    $userWith = $userModel->with(['article'])
        ->withCount(['article'])
        ->withSum(['article'], 'read_num')
        ->withAvg(['article'], 'read_num')
        ->withMax(['article'], 'read_num')
        ->find(1)->toArray();
    dump($userWith);

    // 查询ID=1的用户,关联查询文章,【article】就是UserModel模型中定义的关联方法
    $userWithJon = $userModel->withJoin(['article'])
        ->withCount(['article'])
        ->withSum(['article'], 'read_num')
        ->withAvg(['article'], 'read_num')
        ->withMax(['article'], 'read_num')
        ->find(1)->toArray();
    dd($userWithJon);
}

  • 关联查询使用闭包时,如果只需显示关联模型中的几个字段,field() 方法中必须带上两个模型中的关联字段(下图中的关联字段就是UserModel模型中article()里面的第二个参数[ user_id ])。当然,带上关联字段后,关联字段也会显示出来。
  • 关联查询使用闭包时,如果要过滤关联模型中的几个字段不显示,使用 withoutField() 方法。这时就不用带上关联字段。

3、一对多关联新增

常用新增的使用(下图有执行插入操作后的数据情况),我总共使用了四种方法进行插入,下图可以看见结果。

  • 使用【insert】和【insertGetId】虽说可以插入关联,但是关联字段[ user_id ]不会自动写入数据。而且在设置了自动写入时间的情况下,[ create_time ] 和 [ update_time ] 也没有数据。
  • 使用【save】可以插入关联数据,也可以自动写入关联字段[ user_id ]和[ create_time ] 和 [ update_time ] 的数据。【saveAll】也是可行的。
  • 使用【create】不能写入数据,会直接报错。
  • 从用户模型添加关联数据到文章模型时,我们只需要在用户模型中设置关联模式。在关联模型(ArticleModel)中的相对关联不是必须设置的。
    /**
         * 用户模型中的文章关联:一对多(必须设置才能实现关联数据的添加)
         * hasMany()
         * 第一个参数:要关联的模型类
         * 第二个参数:在关联表中表示当前模型的外键名
         * 第三个参数:当前模型(userModel)的主键名
         * @return \think\model\relation\HasMany
         * @Author: fengzi
         * @Date: 2024/7/3 11:40
         */
        public function article()
        {
            return $this->hasMany(ArticleModel::class,'user_id','id');
        }
    
    /**
         * 文章模型中相对关联的用户模型(通过用户模型添加文章的关联数据时非必须)
         * belongsTo()
         * 第一个参数:关联模型类
         * 第二个参数:在当前模型(ArticleModel)中表示关联模型(UserModel)的外键
         * 第三个参数:关联模型主键
         * @return \think\model\relation\BelongsTo
         * @Author: fengzi
         * @Date: 2024/7/3 13:54
         */
        public function user()
        {
            return $this->belongsTo(UserModel::class, 'user_id', 'id');
        }
    
public function many()
{
    // 实例化模型
    $userModel = app(UserModel::class);

    // 查询ID=10的用户
    $user = $userModel->find(10);
    
    // 使用insert添加ID=10用户的关联文章
    $user->article()->insert(['title' => '厦门旅游', 'status' => 1]);
    
    // 使用insertGetId添加ID=10用户的关联文章
    $user->article()->insertGetId(['title' => '黄山旅游', 'status' => 2]);
    
    // 使用save添加ID=10用户的关联文章
    $user->article()->save(['title' => '泰山旅游', 'status' => 1]);
    
    // 使用create添加ID=10用户的关联文章
    $user->article()->create(['title' => '泰山旅游', 'status' => 2]);

    dd($user->toArray());
}

4、一对多关联删除

一对多的关联删除跟【ThinkPHP一对一关联模型的运用(ORM)】文章中的【1.6.1、with 的关联删除】小节差不多,在此就不在重复赘述了。

在此我再补充一些细节:

  • 关联删除的时候用select()方法查出来的数据不能用together()进行关联数据的删除。
  • 链式操作的方式使用together()的时候一定要注意一个细节:前面查找的数据一定不能为空,不然链式操作直接跟together()会报错( Call to a member function together() on null )。
  • 必须以查询结果的对象进行together()操作(使用find()方法后获取到一个查询结果对象)。不能直接条件查询后进行together()操作,不然会报错“method not exist:think\db\Query->together”。
    public function many()
    {
        // 实例化模型
        $userModel = app(UserModel::class);
    
        // 正确使用:必须以查询结果的对象进行together()操作,使用find()方法后获取到一个查询结果对象。
        $res = $userModel->with(['article'])->where('id', 1)->find()->together(['article'])->delete();
    
        // 错误使用:不能直接条件查询后进行together()操作,不然会报错“method not exist:think\db\Query->together”
        $res = $userModel->with(['article'])->where('id', 1)->together(['article'])->delete();
    
        dd($res);
    }
    

 5、一对多的关联编辑

一对多的关联编辑跟【ThinkPHP一对一关联模型的运用(ORM)】文章中的【1.5、with 关联修改】小节差不多,在此就举几个简单的例子:

public function many()
{
    // 实例化模型
    $userModel = app(UserModel::class);

    // 获取用户ID=4的信息
    $res = $userModel->with(['article'])->where('id', 4)->find();

    // 打印修改前的数据
    dump($res->toArray());

    // 修改用户名
    $res->name = 'xiaohuang';
// 保存修改 $res->save(); // 添加标题为“海口旅游攻略”的新文章 $res->article()->save(['title' => '海口旅游攻略']); // 修改文章ID=7的阅读量 $res->article()->save(['id'=>7, 'read_num' => 1000]); // 查询打印修改后的数据 $info = $userModel->with(['article'])->where('id', 4)->find(); dd($info->toArray()); }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2175862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL - 单表查询

DQL (数据查询语言)是用来查询数据库表中的记录的操作。在实际的业务系统中&#xff0c;查询操作的频率远远高于增删改。常见的查询操作包括条件查询、排序、分组等。 1. DQL 语法 SELECT 字段列表 FROM 表名列表 [WHERE 条件列表] [GROUP BY 分组字段] [HAVING 分组后条件]…

玩转图像处理:Python与OpenCV实现高效绿幕背景替换

文章目录 前言色度抠图技术&#xff08;Chroma Keying&#xff09;基本原理 数据准备代码实现性能分析代码优化优化后的速度 前言 现阶段绿幕抠图有很多种方式&#xff0c;比如色度抠图&#xff08;Chroma Keying&#xff09;、亮度抠图&#xff08;Luma Keying&#xff09;、色…

探索Python网络世界的利器:Requests-HTML库

文章目录 探索Python网络世界的利器&#xff1a;Requests-HTML库背景&#xff1a;为何选择Requests-HTML&#xff1f;什么是Requests-HTML&#xff1f;如何安装Requests-HTML&#xff1f;5个简单库函数的使用方法3个场景下库的使用示例常见Bug及解决方案总结 探索Python网络世界…

Acwing 质数

1.试除法判定质数 首先回顾一下什么是质数&#xff1f; 对所有大于1的自然数&#xff0c;如果这个数的约数只包含1和它本身&#xff0c;则这个数被称为质数或者素数 试除法&#xff1a;对于一个数n&#xff0c;从2枚举到n-1&#xff0c;若有数能够整除n&#xff0c;则说明除…

C# 泛型使用案例_C# 泛型使用整理

一、系统自带常用的泛型 1.字典&#xff0c;集合 //字典 Dictionary<string, int> dic new Dictionary<string, int>(); //泛型集合 List<int> list new List<int>(); 2.泛型委托&#xff0c;输入参数&#xff0c;输出参数 //泛型 委托---输出参…

nuclei配合burpsuite快速生成POC

nuclei配合burpsuite快速生成POC 简介 Nuclei是一款基于YAML语法模板的开发的定制化快速漏洞扫描器。它使用Go语言开发&#xff0c;具有很强的可配置性、可扩展性和易用性 官网&#xff1a;https://nuclei.projectdiscovery.io Nuclei项目地址&#xff1a;https://github.com/…

生物信息常用编辑器:轻量/强大/可定制/跨平台支持的编辑器之神 - vim

Emacs 被誉为神的编辑器&#xff0c;而 vim 是编辑器之神。本人曾经是 Emacs 的粉丝&#xff0c;不过后来不知不觉&#xff0c;已经是 vim 的重度用户&#xff0c;而 Emacs 却很长时间没用了。 如果你开始在生物信息学中编写代码或处理大量文本数据&#xff0c;选择一个合适的文…

【C语言刷力扣】2079.给植物浇水

题目&#xff1a; 解题思路&#xff1a; 面对每一株植物有两种情况 水够 or 水不够&#xff1a; 水够&#xff1a; result 加1即向前走一步水不够&#xff1a; 走回河边再走回来并向前走一步&#xff0c;走到下一植物 result 2 * i 1 int wateringPlants(int* plants, int…

Cluster Explanation via Polyhedral Descriptions

通过多面体描述进行聚类解释 本文关注聚类描述问题&#xff0c;即在给定数据集及其聚类划分的情况下&#xff0c;解释这些聚类的任务。我们提出了一种新的聚类解释方法&#xff0c;通过在每个聚类周围构建一个多面体&#xff0c;同时最小化最终多面体的复杂性或用于描述的特征…

2024-9-28 QT登录框基础练习

1.头文件 #ifndef LOGINWINDOW_H #define LOGINWINDOW_H#include <QWidget> #include <QPushButton> #include <QLineEdit> #include <QVBoxLayout>class LoginWindow : public QWidget {Q_OBJECTpublic:// 构造函数LoginWindow(QWidget *parent nul…

卸载WSL(Ubuntu),卸载linux

禁用 WSL 功能 打开 Windows 功能&#xff1a; 按下 Windows R 打开运行对话框&#xff0c;输入 optionalfeatures&#xff0c;然后按回车。 禁用 WSL&#xff1a; 在弹出的 Windows 功能窗口中&#xff0c;找到 适用于 Linux 的 Windows 子系统&#xff08;Windows Subsystem…

2024年咸宁中级职称水平测试合格公示

工程系列水测合格549人 农业系列水测合格18人 新闻系列水测合格37人 档案系列水测合格16人 看来每年评工程类职称 人员还是占大多数 关于咸宁初级、中级职称评审更多需要了解的可以留言

.NET 开源的功能强大的人脸识别 API

给大家推荐一款.NET 开源提供了强大的人脸识别 API&#xff0c;工具不仅易于集成&#xff0c;还具备高效处理能力。 本文将介绍一款如何利用这些API&#xff0c;为我们的项目添加智能识别的亮点 GitHub 上拥有 1.2k 星标的 C# 面部识别 API 项目&#xff1a;FaceRecognitionD…

传知代码-基于图神经网络的知识追踪方法(论文复现)

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 1.论文概述 论文链接提出了一种基于图神经网络的知识追踪方法&#xff0c;称为基于图的知识追踪&#xff08;GKT&#xff09;。将知识结构构建为图&#xff0c;其中节点对应于概念&#xff0c;边对应于它们之间的…

Jupyter Notebook 更换主题

1、安装 Jupyter 主题 pip install jupyterthemes 2、更新 Jupyter 主题 &#xff08;可选&#xff09; pip install --upgrade jupyterthemes 3、查看可用的 Jupyter 主题 jt -l 4、更换 Jupyter 主题 选择你喜欢的主题后&#xff0c;可以使用以下命令来应用它。更换主题后…

个人健康管理小程序(源码+参考文档+定制)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Python 潮流周刊#71:PyPI 应该摆脱掉它的赞助依赖

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 本周刊由 Python猫 出品&#xff0c;精心筛选国内外的 250 信息源&#xff0c;为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景&#xff1a;帮助所有读者精进 Python 技术&am…

如何安装和设置 Go 版本的 fabric AI 工作流框架?

痛点 今年 6 月份&#xff0c;我给你介绍了 fabric 这款 AI 工作流工具。 它包裹了大量的优秀提示词&#xff0c;可以处理各种你日常工作、学习和科研中的事务性工作。包括但不限于&#xff1a; 从视频当中提取要点撰写博客给研究评分…… 不少读者看过之后&#xff0c;大呼有用…