zoukankan      html  css  js  c++  java
  • THINKPHP_(7)_修改TP源码,支持基于多层关联的任一字段进行排序

    之前博文

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

    基本原理

    (1)前端使用layui框架进行字段显示,比如:

    options.cols=[[ //表头
    {field: "canxunDanweiSchool", title: '单位名称', sort: true, minWidth:150, templet:function(d){
                    var str='';
                    if(d.canxunDanweiSchool)
            {
              if(d.canxunDanweiSchool.title)
              {
                str = d.canxunDanweiSchool.title;
              }
            }
                    return str;
                }},
    ...

    详细内容查阅layui的options设置表格显示,其中sort设置为true

    (2)后端查询的thinkcollection数据按指定字段进行重排。当点击对应的上下三角排序角标的时候,会返回到thinkphp的后端controller中。

    (3)后端从request中取出对应的field值和order值。

     (4)对model返回的thinkcollection数据,按页面点击的排序要求(field和order,即按什么字段,按正序还是倒序进行排序)进行重排。执行的是如下代码:

        public function reSetObject($obj, $srcfrom)
        {
            // 整理变量
            $src = [
                'field' => ''
                ,'order' => 'asc'
                ,'page' => 1
                ,'limit' => 10
            ];
            $src = array_cover($srcfrom, $src) ;
    
            $data = [
                'code' => 0  // ajax请求次数,作为标识符
                ,'msg' => ""  // 获取到的结果数(每页显示数量)
                ,'count' => 0 // 符合条件的总数据量
                ,'data' => '' //获取到的数据结果
            ];
    
            // 整理数据
            $cnt = $obj->count();
            if($cnt > 0)
            {
                if($src['field'] != '') # 排序
                {
                    $obj = $obj->order($src['field'], $src['order']);
                }
                $limit_start = $src['page'] * $src['limit'] - $src['limit'];
                $limit_length = $src['limit'] * 1;
                $obj = $obj->slice($limit_start, $limit_length);
                $data = [
                    'code' => 0  // ajax请求次数,作为标识符
                    ,'msg' => ""  // 获取到的结果数(每页显示数量)
                    ,'count' => $cnt // 符合条件的总数据量
                    ,'data' => $obj //获取到的数据结果
                ];
            }
            return $data;
        }

    上述的核心代码是

    $obj->order

    即,对thinkcollection调用order方法。order执行的具体内容位于thinkphp的源代码Collection.php文件中。

    具体可以见我之前的博文:THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序

    新的问题

    对于多层关联的字段(位于多个不同的表中),如何进一步修正TP源码,以支持排序。

    表的关联关系是:

    (1)本表,其中school_id和xueqi_id两个字段均关联另外一个表.

    (2)第一层关联的两个表:school表和xueqi表。

    school表

     xueqi表

     (3)关联第一层表后,再关联第二层的表,即school表的parent_id关联school表自身,表示上级单位。然后xueqi表的peiyang_category_id和xuenian等均关联category表。

    之前博文中:

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

    TP6中实现多层关联,第一个表关联第二个表查询出的数据,再关联第三个表

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

    中能够查询多层关联数据。通过将位于本表,多层关联的表的字段取出来显示在layui的同一个表格中去后。

     那么问题来了,

    如何实现,按位于多个表的字段进行排序呢?

    解决方案:(再次修改TP源码)

    首先,在layui的options表头配置中,field字段,填入如下内容:

    canxunDanweiSchool.xiaojieShangJiDanwei.jiancheng

    对应的就是表中的“上级单位”那一列。当点击文字旁边的上下三角角标进行排序,就能将这个field内容传回后台。

    然后我们进一步修改order函数,改为:

        public function order(string $field, string $order = 'asc')
        {
            return $this->sort(function ($a, $b) use ($field, $order) {
                //添加对中文的支持。
                //xiaojie add代码,添加对中文的支持。
                //检测field是否为.区分开的多层。
                //$pos = strpos($field, '.');
    //            $field='canxunDanweiSchool.xiaojieShangJiDanwei.jiancheng';
                $pos = strpos($field, '.');
                if($pos!=false){//存在点号
                    $k=explode('.',$field);
                    $fieldA=$a;
                    $fieldB=$b;
                    foreach($k as $value){
                        $fieldA=$fieldA[$value];
                        $fieldB=$fieldB[$value];
                    }
                    $fieldA = $fieldA ?? null;
                    $fieldB = $fieldB ?? null;
                }
                else{
                    $fieldA = $a[$field] ?? null;
                    $fieldB = $b[$field] ?? null;
                }
    
                //注意,如果取出的$fieldA是数字,就不能用preg_match。所以,应该加上一个字符串判断类型。因为有些时候会对数字进行排序。
    
                /*添加对多层关联的支持。*///如果是多层关联数据,比如field传入的数据是canxunDanweiSchool.xiaojieShangJiDanwei.jiancheng
                //我们就可以用类似下述的代码进行强制关联。
    
    
                if (isset($fieldA) && isset($fieldB) && is_string($fieldA) &&is_string($fieldB) && preg_match("/[x7f-xff]/", $fieldA)){ //如果字段内容中有中文。
                    $coll = collator_create( 'zh-CN' );
                    $res  = collator_compare( $coll, $fieldA, $fieldB );
                    return 'desc' == strtolower($order) ? $res<0 : $res>0;
                }
                else{
    //                $fieldA = $a[$field] ?? null;
    //                $fieldB = $b[$field] ?? null;
    
                    return 'desc' == strtolower($order) ? $fieldB > $fieldA : $fieldA > $fieldB;
                }
            });
        }

    上述代码,相较于之前博文THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序中的内容,又主要添加了如下代码:

                $pos = strpos($field, '.');
                if($pos!=false){//存在点号
                    $k=explode('.',$field);
                    $fieldA=$a;
                    $fieldB=$b;
                    foreach($k as $value){
                        $fieldA=$fieldA[$value];
                        $fieldB=$fieldB[$value];
                    }
                    $fieldA = $fieldA ?? null;
                    $fieldB = $fieldB ?? null;
                }

    即对多层关联的字段进行识别。如果是多层关联的数据,我们就一直定位到最后的那个表的那个字段,然后按那个字段进行排序。最后的排序结果如下:

     可以看到,实现了按两层关联的那个表的jiancheng字段进行了中文拼音的排序。

    你永远不知道未来会有什么,做好当下。技术改变世界,欢迎交流。
  • 相关阅读:
    安装acdsee 3.1后出错
    周末游山
    SQL Server不存在或访问被拒绝 Windows里的一个bug
    将数据库的存储过程及其参数导出来的方法
    VS出错问题集锦
    25 网页设计之页脚设计灵感
    需求沟通和实施
    Mootools插件闪烁的标题
    最近常常干出一些骑着驴找驴的事来
    php表单在提交之后再后退,表单的内容默认是被清空的
  • 原文地址:https://www.cnblogs.com/xiaojieshisilang/p/14864272.html
Copyright © 2011-2022 走看看