之前博文

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

基本原理

(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)后端查询的think\collection数据按指定字段进行重排。当点击对应的上下三角排序角标的时候,会返回到thinkphp的后端controller中。

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

(4)对model返回的think\collection数据,按页面点击的排序要求(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

即,对think\collection调用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字段进行了中文拼音的排序。

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

  1. THINKPHP_(1)_修改TP源码,支持对中文字符串按拼音进行排序。

    问题:TP从服务器数据中取出的collection数据,当进一步在网页中进行分页显示时,需要调用order函数,实现类似如下图的排序. 当点击页面中的相关内容时,实现对服务器数据进行重排,就要调用TP ...

  2. 修改json源码支持datetime序列化

    修改json源码支持datetime序列化 import json import datetime now = datetime.datetime.today() json.dumps(now) 抛出 ...

  3. 修改Cosbench源码 支持s3的 http range request 测试场景

    在视频点播的业务应用场景中,用户使用了ffmpeg工具做视频实时转码用. 而ffmpeg使用range 请求.而Cosbench不支持这种测试场景,所以需要修改源码支持这种测试场景. HTTP 协议介 ...

  4. 修改CAS源码是的基于DB的认证方式配置更灵活

    最近在做CAS配置的时候,遇到了数据源不提供密码等数据的情况下,怎样实现密码输入认证呢? 第一步:新建Java项目,根据假面算法生成CAS加密工具 出于保密需要不提供自定义的加密工具,在您的实际项目中 ...

  5. 32.修改IK分词器源码来基于mysql热更新词库

    主要知识点, 修改IK分词器源码来基于mysql热更新词库     一.IK增加新词的原因 在第32小节中学习到了直接在es的词库中增加词语,来扩充自已的词库,但是这样做有以下缺点: (1)每次添加完 ...

  6. 《Flink SQL任务自动生成与提交》后续:修改flink源码实现kafka connector BatchMode

    目录 问题 思路 kafka参数问题 支持batchmode的问题 参数提交至kafkasource的问题 group by支持问题 实现 编译 测试 因为在一篇博文上看到介绍"汽车之家介绍 ...

  7. 修改FFMpeg源码—捕获丢包

    概述 最近我们项目有一个需求就是解决客户端播放RTSP视频流花屏的问题,一般来说丢包就会引起花屏,导致客户端花屏的因素又有很多,比如说: 相机到服务器丢包 服务器到客户端丢包 等等... 其中服务器到 ...

  8. 修改spring源码重写classloader实现项目加密

      (一)操作方法和spring源码添加修改部分 事先说明:spring源码要下载好,会有修改spring的源码操作,本文和本作者所依赖的spring项目的版本是3.1.1,spring4及以上源码对 ...

  9. 修改VCL源码实现自定义输入对话框

    来自:https://yq.aliyun.com/wenji/88428 通过修改VCL源码实现自定义输入对话框 在BCB中有两个函数可以实现输入对话框:InputBox和InputQuery,其实I ...

随机推荐

  1. 【.NET 与树莓派】数模转换

    在开始之前,需要说明一对很耳熟的概念--数字信号 & 模拟信号. 这些概念的理论有些复杂,你如果相当有兴趣,可以找来有关的文献细细研究:若你不关心那是啥只想知道咋用,那就通俗但不庸俗地理解一下 ...

  2. 【ORM】Mybatis与JPA的区别

    Mybatis与JPA的区别: 1.ORM映射不同: Mybatis是半自动的ORM框架,提供数据库与结果集的映射: JPA(Hibernate)是全自动的ORM框架,提供对象与数据库的映射: 2.可 ...

  3. Windows核心编程 第十四章 虚拟内存

    第1 4章 虚 拟 内 存 <这一章没啥,是说的几个内存相关的函数 > 14.1 系统信息 许多操作系统的值是根据主机而定的,比如页面的大小,分配粒度的大小等.这些值决不应该用硬编码的形式 ...

  4. ADB调试工具的使用

    ADB(Android Debug Bridge)安卓调试桥,ADB工具是可以方便调试安卓应用的工具. ADB的安装 下载ADB工具,解压, 将ADB工具的目录加入系统环境变量中,打开CMD窗口,输入 ...

  5. 神经网络与机器学习 笔记—Rosenblatt感知器收敛算法C++实现

    Rosenblatt感知器收敛算法C++实现 算法概述 自己用C++实现了下,测试的例子和模式用的都是双月分类模型,关于双月分类相关看之前的那个笔记: https://blog.csdn.net/u0 ...

  6. React-条件渲染

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...

  7. js中return;、return true、return false;区别

    一.返回控制与函数结果 语法为:return 表达式 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果 二.返回控制 无函数结果,语法为:return; 在大多数情况下,为事件处理函数返 ...

  8. cmake VTK visual studio 2010

    使用cmake在configure之后,出现了以下错误,导致编译无法进行 The C compiler "cl" is not able to compile a simple t ...

  9. Linux下查看在线用户及用户进程

    #该服务器下的所有用户运行进程的情况 ps -ax -u #查看java程序下用户的进程情况 ps -ax -u |grep java   或  ps aux|grep java cat /etc/p ...

  10. Java并发-线程池篇-附场景分析

    作者:汤圆 个人博客:javalover.cc 前言 前面我们在创建线程时,都是直接new Thread(): 这样短期来看是没有问题的,但是一旦业务量增长,线程数过多,就有可能导致内存异常OOM,C ...