2.withJoin的特性

2.1 第一个特性

TP模型的多表关联查询和多表字段的关键字搜索

的博文中,阐述了利用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查询概念,请搜索网络)。即如果将博文

TP模型的多表关联查询和多表字段的关键字搜索

中的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和多层关联的深入分析的更多相关文章

  1. THINKPHP_(2)_TP模型的多表关联查询和多表字段的关键字搜索。

    问题: 上述内容中,标题和学年属于一个数据表.分类则属于另外一个数据表,并且是利用id关联后,另外一个数据表中的title字段. 需要设置关键字搜索,实现多表关联查询和多表字段的关键字搜索. 解决方法 ...

  2. THINKPHP_(8)_修改TP源码,支持基于多层关联的任一字段进行排序

    之前博文 前述博文THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序,其解决的主要问题是,对于查询出的think\collection数据,按指定字段对数据进行排序,从而在页面上进 ...

  3. Entity Framework 6 Recipes 2nd Edition(10-5)译 -> 在存储模型中使用自定义函数

    10-5. 在存储模型中使用自定义函数 问题 想在模型中使用自定义函数,而不是存储过程. 解决方案 假设我们数据库里有成员(members)和他们已经发送的信息(messages) 关系数据表,如Fi ...

  4. Entity Framework 6 Recipes 2nd Edition(10-6)译 -> TPT继承模型中使用存储过程

    10-6. TPT继承模型中使用存储过程 问题 想在一个TPT继承模型中使用存储过程 解决方案 假设已有如Figure 10-6所示模型. 在模型里, Magazine(杂志) and DVD继承于基 ...

  5. Entity Framework 6 Recipes 2nd Edition(10-7)译 -> TPH继承模型中使用存储过程

    10-7. TPH继承模型中使用存储过程 问题 用一个存储过程来填充TPH继承模型的实体 解决方案 假设已有如Figure 10-7所示模型. 我们有两个派生实体: Instructor(教员)和St ...

  6. [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

    目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...

  7. thinkphp在模型中自动完成session赋值

    相信用过thinkphp的用户都知道thinkphp的模型可以完成很多辅助功能,比 如自动验证.自动完成等,今天在开发中遇到自动完成中需要获取session值 然后自动赋值的功能,具体看代码:clas ...

  8. [Asp.net MVC]Asp.net MVC5系列——从控制器访问模型中的数据

    目录 概述 从控制器访问模型中的数据 强类型模型与@model关键字 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net M ...

  9. django模型中的抽象类(abstract)

    首先介绍下django的模型有哪些属性:先看例子: Django 模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性.以下对此作一总结: abstract 这个属性是定义当前的模 ...

随机推荐

  1. Redis系统学习之事物

    Redis事物操作 Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证: 批量操作在发送 EXEC 命令前被放入队列缓存. 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败, ...

  2. jQuery监控键盘事件

    <!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  3. thinkphp5的extend怎么用?

    http://www.newthink.cc/2017/09/13/thinkphp5%E7%9A%84extend%E6%80%8E%E4%B9%88%E7%94%A8%EF%BC%9F/#i-2

  4. 【Java注解】@PostConstruct 注解相关

    不多逼逼,直接看注解上面的文档, @PostConsturct PostConstruct注释用于需要执行的方法在依赖注入完成后执行任何初始化.这个方法必须在类投入服务之前调用. 这个所有支持依赖关系 ...

  5. 缓冲区溢出分析第06课:W32Dasm缓冲区溢出分析

    漏洞报告分析 学习过破解的朋友一定听说过W32Dasm这款逆向分析工具.它是一个静态反汇编工具,在IDA Pro流行之前,是破解界人士必然要学会使用的工具之一,它也被比作破解界的"屠龙刀&q ...

  6. POJ1466 最大点权独立集

    题意:       给你n个人,再给你每个人都喜欢哪些人,让你找到一个最大的集合数,要求这个集合里面任意两个人都不喜欢彼此. 思路:       直接就是在问最大点权独立集元素个数,没啥解释的一遍二分 ...

  7. Android进程so注入Hook java方法

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/53769331 Andorid的Hook方式比较多,现在来学习下,基于Android ...

  8. 仁者见仁:缓冲区栈溢出之利用 Exploit 形成完整攻击链完全攻略(含有 PayLoad)

    > 前言 内存缓冲区溢出又名 Buffer OverFlow,是一种非常危险的漏洞,在各种操作系统和应用软件中广泛存在.利用缓冲区溢出进行的攻击,小则导致程序运行失败.系统宕机等后果,大则可以取 ...

  9. Docker用Dockerfile定制镜像

    用Dockerfile定制镜像 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那之前提示的无法重复的问题 ...

  10. 用 shell 脚本制造连接频繁中断的场景

    问题的提出 最近在准备客户端的新版本,在内部灰度过程中,发现一类奇怪的 dump,通过查看日志和堆栈,可以确定是因为每次连上后台就被后台断开了.导致多次重连后随机发生的崩溃.dump 和日志都无法提供 ...