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 这个属性是定义当前的模 ...
随机推荐
- .Net之静态资源
介绍 静态文件都存储在Core Web根目录中.默认目录是<content_root>/wwwroot,但可通过 UseWebRoot方法更改访问目录.而content_root是指web ...
- 怎样用SQL修改某个字段的部分内容
方法:update dede_addonarticle set body = replace(body,'#p#分页标题#e#',' ') where body like '%#p#分页标题#e#%'
- Linux中的shell和bash
目录 shell shell script sh bash Dash tty .pty 和 pts 学安全的我们,经常会听到说获得某服务器的shell,就是指获得某个服务器的操作权限.我们学习linu ...
- Win64 驱动内核编程-10.突破WIN7的PatchGuard
突破WIN7的PatchGuard WIN64 有两个内核保护机制,KPP 和 DSE.KPP 阻止我们 PATCH 内核,DSE 拦截我们加载驱动.当然 KPP 和 DSE 并不是不可战胜的,WIN ...
- W32Dasm缓冲区溢出分析【转载】
课程简介 在上次课程中与大家一起学习了编写通用的Shellcode,也提到会用一个实例来展示Shellcode的溢出. 那么本次课程中为大家准备了W32Dasm这款软件,并且是存在漏洞的版本.利用它的 ...
- ecloud云主机限速相关配置说明
目前与云主机限速相关的内容共有三处: neutron qos-xxx命令,通过neutron qos的形式为云主机port绑定相应的网络限速策略(对应弹性公网IP) 通过flavor对云主机进行默认限 ...
- Day001 Typora Markdown语法学习
# Markdown语法 ## 标题 ### 三级标题 #### 四级标题 注:最多支持到六级标题 ## 字体 **hello,world!** *hello,world!* ***hello,wor ...
- Android学习之TTS踩坑笔记
•前言 最近在做一款英文词典的 APP,做到语音模块的时候,我裂开,从网上搜索了各种博客,各种瞎捣鼓,模拟器就是不发音: 辗转反侧数日,终于让我找到解决之法,接下来就本次测试列出一些需要(必须)解决的 ...
- Day015 Error和Exception
Error和Exception 什么是异常 实际工作中,遇到的情况不可能是非常完美的.比如:你写的某个模块,用户输入不一定符合你的要求.你的程序要打开某个文件,这个文件可能不存在或者文件的格式不对,你 ...
- 容器进阶:OCI与容器运行时
Blog:博客园 个人 什么是容器运行时(Container Runtime) Kubernetes节点的底层由一个叫做容器运行时的软件进行支撑,它负责比如启停容器 这样的事情.最广为人知的容器运行时 ...