THINKPHP_(4)_TP模型中with、withJoin和多层关联的深入分析
2.withJoin的特性
2.1 第一个特性
的博文中,阐述了利用withJoin进行关联查询的情况。这里补充一个命名特性(经过调试确认)
即关系命名的,必须与模型名保持一致,否则withJoin无法使用。(当这个不满足时,with仍可使用。大家可以调试确认)

即关系名中的School和Xueqi等必须与关联模型一致,才能使用withJoin。
2.12第二个特性
withJoin的关联查询,只支持单层关联,不支持多层。
比如:
->withJoin(
[
'canxunDanweiSchool' => function($query){
$query
->withJoin(['dwJibie','xiaojieShangJiDanwei'])
;
},
'canxunpeiyangjihuaXueqi' => function($query) use($src){
$query
->withJoin(['glCategory','pyCategory','xnCategory'])
;
},
]
)
这里可能想表达,"多层关联,即先关联到School表,再从school表中多层关联到Category表。类似的,先关联到Xueqi,再关联到Category表。“
注意,此时,使用如下代码进行单层关联查询,是可行的。
->when(count($src['canxunPeiyangjihua_pyCategory']) > 0, function($query) use($src){
$query->where('canxunpeiyangjihuaXueqi.peiyang_category_id', 'in', $src['canxunPeiyangjihua_pyCategory']);
})
但是,无法返回多层关联数据,即withJoin无法返回二层关联的glCategory、dwJibie等关系中的任何数据。
返回多层关联数据,只能用with,而不能用withJoin。详见博文:
TP6中实现多层关联,第一个表关联第二个表查询出的数据,再关联第三个表
3.with的特性
虽然前述博文中,with能够查询出多层的数据,但是with不支持类似于withJoin的inner Join查询(关于inner Join查询概念,请搜索网络)。即如果将博文
中的withJoin换成with,是无法实现withJoin功能的。
即使在with的代码中,添加where,那么只能实现的是关联表中的数据过滤,而不涉及本表,即不能实现join的功能。比如,如下代码:
->with(
[
'canxunDanweiSchool' => function($query){
$query
->with(['dwJibie','xiaojieShangJiDanwei'])
// ->field('id, title, jiancheng')//如果通过field设置输出字段,会限制关联查询dwJibie
// ->withField('dwJibie')
;
},
'canxunpeiyangjihuaXueqi' => function($query) use($src){
$query
->with(['glCategory','pyCategory','xnCategory'])
// ->when(count($src['canxunPeiyangjihua_pyCategory']) > 0, function($query) use($src){
// $query->where('peiyang_category_id', 'in', $src['canxunPeiyangjihua_pyCategory']);
//// ->field('id, title, jiancheng')//如果通过field设置输出字段,会限制关联查询dwJibie
//// ->withField('dwJibie')
// })
;
},
]
)
其中在关系中添加的where查询,只会使得关联表中的数据进行过滤,不会对本表查询的数据进行where过滤。
比如:表a的某行数据data1,在表b中关联的某行数据,不满足where条件,那么返回的数据是,表a中的data1仍然被返回,只是表b中对应的关联数据被筛选掉。这达不到innerJoin功能
4.实现多层关联数据查询,并在关联表中实现where功能,inner join到本表。
代码如下:
// $xxx=Db::query('select id from cj_canxundanwei');
// 整理参数
$src = [
'school_id' => array()
,'xueqi_id' => array()
,'canxunPeiyangjihua_pyCategory'=> array() //搜索培养大类
];
$src = array_cover($srcfrom, $src);
$src['school_id'] = strToArray($src['school_id']);
$src['xueqi_id'] = strToArray($src['xueqi_id']);
$src['canxunPeiyangjihua_pyCategory'] = strToArray($src['canxunPeiyangjihua_pyCategory']);
// 查询数据
$data = $this
->with(
[
'canxunDanweiSchool' => function($query){
$query
->with(['dwJibie','xiaojieShangJiDanwei'])
// ->field('id, title, jiancheng')//如果通过field设置输出字段,会限制关联查询dwJibie
;
},
'canxunpeiyangjihuaXueqi' => function($query) use($src){
$query
->with(['glCategory','pyCategory','xnCategory'])
;
},
]
)
->when(count($src['school_id']) > 0, function($query) use($src){
$query->where('school_id', 'in', $src['school_id']);
})
->when(count($src['xueqi_id']) > 0, function($query) use($src){
$query->where('xueqi_id', 'in', $src['xueqi_id']);
})
->when(count($src['canxunPeiyangjihua_pyCategory']) > 0, function($query) use($src) {
/*
* 使用原生SQL语句
*/
// Db::query('select id from cj_canxundanwei');
// $a='(';
// foreach($src['canxunPeiyangjihua_pyCategory'] as $value){
// $a=$a.(String)$value.',';
// }
// $a=substr($a,0,strlen($a)-1);
// $a=$a.')';
// $xxx=Db::query('select c.id from cj_canxundanwei c INNER JOIN cj_xueqi x ON c.xueqi_id = x.id where x.peiyang_category_id in '.$a);
// $ddd=array();
// foreach($xxx as $value){
// array_push($ddd,(String)$value['id']);
// }
// $query->where('id','in',$ddd);
/*
* 使用原生SQL语句
*/
$sch = new CX;
$eee=$sch->withJoin(['canxunpeiyangjihuaXueqi'=>function($query){
$query->field('peiyang_category_id');
},])->where("canxunpeiyangjihuaXueqi.peiyang_category_id",'in', $src['canxunPeiyangjihua_pyCategory'])
->field('Canxundanwei.id')->select();
$query->where('id','in',$eee);
})
->select();
即,只能使用原生sql语句。其中被注释"使用原生sql语句"注释掉的代码中为正确内容。而如下代码中执行的内容,返回的数据是thinkPHP的collection数据
$sch = new CX;
$eee=$sch->withJoin(['canxunpeiyangjihuaXueqi'=>function($query){
$query->field('peiyang_category_id');
},])->where("canxunpeiyangjihuaXueqi.peiyang_category_id",'in', $src['canxunPeiyangjihua_pyCategory'])
->field('Canxundanwei.id')->select();
所以,
$query->where('id','in',$eee);
执行会失败。
注意,db引用的是think\facade\Db类。
即,只能使用原生sql语句,实现多层关联数据查询的同时,同时再实现inner Join的功能。如有其余方法,请评论。
THINKPHP_(4)_TP模型中with、withJoin和多层关联的深入分析的更多相关文章
- THINKPHP_(2)_TP模型的多表关联查询和多表字段的关键字搜索。
问题: 上述内容中,标题和学年属于一个数据表.分类则属于另外一个数据表,并且是利用id关联后,另外一个数据表中的title字段. 需要设置关键字搜索,实现多表关联查询和多表字段的关键字搜索. 解决方法 ...
- THINKPHP_(8)_修改TP源码,支持基于多层关联的任一字段进行排序
之前博文 前述博文THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序,其解决的主要问题是,对于查询出的think\collection数据,按指定字段对数据进行排序,从而在页面上进 ...
- Entity Framework 6 Recipes 2nd Edition(10-5)译 -> 在存储模型中使用自定义函数
10-5. 在存储模型中使用自定义函数 问题 想在模型中使用自定义函数,而不是存储过程. 解决方案 假设我们数据库里有成员(members)和他们已经发送的信息(messages) 关系数据表,如Fi ...
- Entity Framework 6 Recipes 2nd Edition(10-6)译 -> TPT继承模型中使用存储过程
10-6. TPT继承模型中使用存储过程 问题 想在一个TPT继承模型中使用存储过程 解决方案 假设已有如Figure 10-6所示模型. 在模型里, Magazine(杂志) and DVD继承于基 ...
- Entity Framework 6 Recipes 2nd Edition(10-7)译 -> TPH继承模型中使用存储过程
10-7. TPH继承模型中使用存储过程 问题 用一个存储过程来填充TPH继承模型的实体 解决方案 假设已有如Figure 10-7所示模型. 我们有两个派生实体: Instructor(教员)和St ...
- [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则
目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...
- thinkphp在模型中自动完成session赋值
相信用过thinkphp的用户都知道thinkphp的模型可以完成很多辅助功能,比 如自动验证.自动完成等,今天在开发中遇到自动完成中需要获取session值 然后自动赋值的功能,具体看代码:clas ...
- [Asp.net MVC]Asp.net MVC5系列——从控制器访问模型中的数据
目录 概述 从控制器访问模型中的数据 强类型模型与@model关键字 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net M ...
- django模型中的抽象类(abstract)
首先介绍下django的模型有哪些属性:先看例子: Django 模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性.以下对此作一总结: abstract 这个属性是定义当前的模 ...
随机推荐
- 753. Cracking the Safe
There is a box protected by a password. The password is n digits, where each letter can be one of th ...
- 【JDK8】Java8 优雅的异步调用API CompletableFuture
1.CompletableFuture是什么? CompletableFuture是JDK8的新特性之一,是异步调用相关的API,用于简化异步调用,提高异步调用的效率 2.CompletableFut ...
- Windows PE导出表编程2(重组导出表函数地址)
本次要做的尝试是通过修改导出表的函数地址,实现程序功能的更改,实现这个最大的限制就是堆栈平衡问题. 先写一个DLL和EXE为了测试. DLL代码如下: 这样的话有两个导出函数(我们假设是一个密码验证之 ...
- 修改linux默认文件创建权限-umask命令解析
umask值用于设置用户在创建文件时的默认权限,当我们在系统中创建目录或文件时,目录或文件所具有的默认权限就是由umask值决定的. 对于root用户,系统默认的umask值是0022:对于普通用户, ...
- 百度地图api逆地址解析 PHP
一.说明:逆地址查询就是根据经纬度信息获取地址位置信息 二.参数:$lat:纬度值 ,$lng:经度值 ,$ak = 自己的AK:(百度地图开放平台对应ak链接:http://lbsyun.baidu ...
- C#中的委托(Update)
什么是委托? 委托(delegate)是一种托管方法的数据结构,它是一种引用类型,是对方法的引用.如果说int,string等是对数据类型的定义,那么委托就类似于对"方法类型"的定 ...
- MongoDB评论管理
MongoDB简介 文章评论数据分析 相较于一般数据,文章评论一般有如下特点: 数据量巨大.通常评论量要比帖子.文章大很多 写入操作频繁. 价值较低.一般来说,我们的主要目标还是在帖子(文章)本身. ...
- 用 edgeadm 一键安装边缘 K8s 集群和原生 K8s 集群
背景 目前,很多边缘计算容器开源项目在使用上均存在一个默认的前提:用户需要提前准备一个标准的或者特定工具搭建的 Kubernetes 集群,然后再通过特定工具或者其他方式在集群中部署相应组件来体验边缘 ...
- printf/scanf格式
(1)打印字符 char c; printf("%c",c); (2)打印整形 int i; printf("%d",i); //有符号十进制数 printf( ...
- OO第一单元总结——表达式求导
第一次作业 (1) UML结构图 (2)结构分析 Polynomial 类是对输入的字符串进行预处理,其中包括判断格式是否合法,运算符简化,分割成项等方法. Polynomial处理后得到的每一个项的 ...