• THINKPHP_(4)_TP模型中with、withJoin和多层关联的深入分析


    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功能。

    即无法通过with中的where语句来对本表返回的数据进行筛选。而join是要实现这种功能的。

    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引用的是thinkfacadeDb类。

    即,只能使用原生sql语句,实现多层关联数据查询的同时,同时再实现inner Join的功能。如有其余方法,请评论。

    你永远不知道未来会有什么,做好当下。技术改变世界,欢迎交流。
  • 相关阅读:
    微信小程序
    svn
    当滑动条滑动到某一位置触发js
    css固定页面
    css三级菜单
    h5时钟
    DOM节点
    应用r.js来优化你的前端
    浅谈javascript中的作用域
    javascript 中的 arguments,callee.caller,apply,call 区别
  • 原文地址:https://www.cnblogs.com/xiaojieshisilang/p/14847570.html
Copyright © 2020-2023  润新知