Yii 2 数据排序实战指南:深入解析 yii\data\Sort 的配置、原理与数据提供者集成
后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载当页面需要展示多行数据且允许终端用户按照某一列或某几列进行排序时Yii 2 提供了专门的[[yii\data\Sort]]对象来承载整套排序模式信息。本文以 output-sorting.md 为骨架结合框架源码与测试用例完整讲解yii\data\Sort的声明方式、配置参数、请求参数解析、排序链接生成以及与 ActiveDataProvider、ArrayDataProvider、SqlDataProvider 等数据提供者的集成原理帮助你写出真正可落地、可复用的 Yii 2 排序功能。一、Sort 对象的三个核心维度yii\data\Sort位于 framework/data/Sort.php继承自yii\base\BaseObject通过三个属性完整描述一套排序模式$attributes声明数据允许按哪些“属性”排序。一个属性可以简单对应模型的一个属性详见 模型属性也可以是由多个模型属性或数据库列组合而成的复合属性。$attributeOrders返回当前请求中各属性对应的排序方向SORT_ASC升序 /SORT_DESC降序以属性名为键。$orders返回底层列级别的排序方向映射键是真实的列名或排序表达式值是对应的方向常量。该数组可以直接喂给数据库查询构造ORDER BY子句。二、声明可排序属性简单属性与复合属性要使用yii\data\Sort第一步是声明允许排序的属性然后从attributeOrders或orders中取出当前请求的排序信息用它定制数据查询。以下是文档中的完整示例use yii\data\Sort; $sort new Sort([ attributes [ age, name [ asc [first_name SORT_ASC, last_name SORT_ASC], desc [first_name SORT_DESC, last_name SORT_DESC], default SORT_DESC, label Name, ], ], ]); $articles Article::find() -where([status 1]) -orderBy($sort-orders) -all();上面声明了两个可排序属性age和name。2.1 简单属性ageage对应ArticleActive Record 类的age属性它是一个简单属性等价于下面的完整声明age [ asc [age SORT_ASC], desc [age SORT_DESC], default SORT_ASC, label Inflector::camel2words(age), ]也就是说当你只写属性名字符串形式时Yii 会自动生成与其同名的列、默认升序方向并用Inflector::camel2words()生成标签。这一归一化逻辑可以在Sort::init()中看到framework/data/Sort.phppublic function init() { $attributes []; foreach ($this-attributes as $name $attribute) { if (!is_array($attribute)) { $attributes[$attribute] [ asc [$attribute SORT_ASC], desc [$attribute SORT_DESC], ]; } elseif (!isset($attribute[asc], $attribute[desc])) { $attributes[$name] array_merge([ asc [$name SORT_ASC], desc [$name SORT_DESC], ], $attribute); } else { $attributes[$name] $attribute; } } $this-attributes $attributes; }注意如果 Sort 对象已经创建完成再对其属性进行配置就必须使用完整格式每个属性都必须包含asc和desc元素。2.2 复合属性namename由Article的first_name和last_name两列组合而成采用数组结构声明asc/desc分别指定按该属性升序、降序排序时的实际列与方向。值可以是一个列简单排序也可以是多个列复合排序。default指定该属性首次被请求排序时采用的默认方向缺省为升序SORT_ASC。label调用Sort::link()生成排序链接时使用的标签文本若不设置Yii 会用Inflector::camel2words()从属性名自动生成。注意该标签不会被 HTML 编码如需转义请自行处理。2.3 直接排序表达式2.0.12自 2.0.12 起asc/desc还可以直接写成一个排序表达式字符串便于使用数据库专属特性。例如 PostgreSQL 的空值排序控制name [ asc [[last_name]] ASC NULLS FIRST, // PostgreSQL 专属特性 desc [[last_name]] DESC NULLS LAST, ]此时getOrders()会把该字符串原样放入orders数组由查询构造器Query Builder解析处理测试用例 SortTest::testGetExpressionOrders 验证了这一点。三、将排序信息应用到数据查询拿到orders后直接传给查询的orderBy()即可$articles Article::find() -where([status 1]) -orderBy($sort-orders) -all();Info可以直接把$sort-orders的值喂给数据库查询构造ORDER BY子句。不要使用$sort-attributeOrders因为有些属性是复合属性数据库查询无法直接识别例如上面name对应的真实列是first_name与last_name。从源码看getOrders()framework/data/Sort.php会遍历attributeOrders把每个属性的asc/desc定义展开成真实列映射若定义是数组/可遍历对象则展开为列 方向若是字符串表达式则直接追加到$orders数组中public function getOrders($recalculate false) { $attributeOrders $this-getAttributeOrders($recalculate); $orders []; foreach ($attributeOrders as $attribute $direction) { $definition $this-attributes[$attribute]; $columns $definition[$direction SORT_ASC ? asc : desc]; if (is_array($columns) || $columns instanceof \Traversable) { foreach ($columns as $name $dir) { $orders[$name] $dir; } } else { $orders[] $columns; } } return $orders; }四、生成排序链接link() 与 createUrl()调用Sort::link()可以生成一个终端用户点击即可请求按指定属性排序的超链接Sort::createUrl()则只生成可排序的 URL。文档示例// 指定生成 URL 所用的路由若不指定则使用当前请求的路由 $sort-route article/index; // 依次展示按 name 和 age 排序的链接 echo $sort-link(name) . | . $sort-link(age); // 输出/index.php?rarticle%2Findexsortage echo $sort-createUrl(age);4.1 link() 的细节行为结合源码framework/data/Sort.phplink()会依次完成若当前该属性已在排序中则根据方向为a附加 CSS 类asc或desc若$options[class]已有值则追加否则新建通过createUrl()生成目标 URL在链接标签上写入data-sort属性值为createSortParam()生成的排序参数供前端 JavaScript 增强交互使用确定标签文本优先取$options[label]其次取$attributes[$attribute][label]再其次通过modelClass实例的getAttributeLabel()获取2.0.49最后退回Inflector::camel2words($attribute)。createUrl()framework/data/Sort.php会把新的排序参数写入$params[$this-sortParam]以$this-route缺省为当前控制器路由Yii::$app-controller-getRoute()作为路由交给urlManager缺省为应用组件urlManager生成 URL传入$absolute true可生成绝对 URL。4.2 链接方向的智能切换createSortParam()framework/data/Sort.php体现了“点击切换方向”的逻辑若当前该属性未在排序中使用定义里的default缺省SORT_ASC作为方向若已在排序中单属性模式下升序变降序、降序变升序多属性模式下升序变降序降序则从排序中移除最终把方向编码为属性名升序或-属性名降序多个属性用separator默认,连接。测试 SortTest::testCreateSortParam 覆盖了各种状态切换例如当sort参数为-age时再请求age排序生成的参数是空字符串即取消排序。五、请求参数解析sort 参数、defaultOrder 与 sortParamyii\data\Sort通过sort查询参数判断用户请求了哪些属性、以什么方向排序。参数格式为升序直接写属性名降序在属性名前加-前缀多属性用分隔符连接例如sortage,-name表示按age升序、name降序。defaultOrder当请求中没有sort参数时使用该属性指定的默认排序格式为[属性名 SORT_ASC|SORT_DESC, ...]。sortParam自定义查询参数名默认是sort。解析过程在getAttributeOrders()framework/data/Sort.php中public function getAttributeOrders($recalculate false) { if ($this-_attributeOrders null || $recalculate) { $this-_attributeOrders []; if (($params $this-params) null) { $request Yii::$app-getRequest(); $params $request instanceof Request ? $request-getQueryParams() : []; } if (isset($params[$this-sortParam])) { foreach ($this-parseSortParam($params[$this-sortParam]) as $attribute) { $descending false; if (strncmp($attribute, -, 1) 0) { $descending true; $attribute substr($attribute, 1); } if (isset($this-attributes[$attribute])) { $this-_attributeOrders[$attribute] $descending ? SORT_DESC : SORT_ASC; if (!$this-enableMultiSort) { return $this-_attributeOrders; } } } return $this-_attributeOrders; } if (empty($this-_attributeOrders) is_array($this-defaultOrder)) { $this-_attributeOrders $this-defaultOrder; } } return $this-_attributeOrders; }要点请求参数来源默认是Yii::$app-request-getQueryParams()即$_GET也可通过$params属性显式指定例如为所有链接统一追加锚点array_merge($_GET, [# my-hash])见 framework/data/Sort.php。解析出的属性如果不在attributes声明中会被忽略防止注入未知列。parseSortParam()是受保护方法默认按separator拆分字符串子类可重写它以支持自定义参数格式例如把sort参数解析为结构化数组——测试中的 CustomSort 就是这样一个示例。六、多属性同时排序enableMultiSort默认情况下enableMultiSort false即同一时刻数据只能按一个属性排序getAttributeOrders()遇到第一个有效属性即返回createSortParam()也只保留单一属性。将其设为true后sort参数可以携带多个属性如age,-name排序同时生效。测试 SortTest::testGetOrders 验证了两种模式下的差异启用多排序时getOrders()返回 3 个列映射age、first_name、last_name关闭后只剩 1 个。七、与数据提供者Data Provider的集成yii\data\Sort最常用的场景是搭配各类数据提供者使用。BaseDataProvider::setSort()framework/data/BaseDataProvider.php接受三种值配置数组class缺省为yii\data\Sort若提供者设置了id还会自动把sortParam命名为{id}-sort避免多个数据提供者共用同一sort参数Sort或其子类的实例false表示禁用排序。7.1 ActiveDataProvider在 framework/data/ActiveDataProvider.php 中排序结果通过addOrderBy()附加到克隆的查询上if (($sort $this-getSort()) ! false) { $query-addOrderBy($sort-getOrders()); }setSort()被重写framework/data/ActiveDataProvider.php传入排序配置后会校验查询是否实现了ActiveQueryInterface。典型用法$provider new ActiveDataProvider([ query Article::find()-where([status 1]), sort [ attributes [age, name], defaultOrder [age SORT_DESC], ], ]);7.2 ArrayDataProvider对于内存数组数据排序在 framework/data/ArrayDataProvider.php 中通过ArrayHelper::multisort()完成并受$sort-sortFlags默认SORT_REGULAR自 2.0.33 起可配置影响protected function sortModels($models, $sort) { $orders $sort-getOrders(); if (!empty($orders)) { ArrayHelper::multisort($models, array_keys($orders), array_values($orders), $sort-sortFlags); } return $models; }7.3 SqlDataProvider对于原生 SQL 查询framework/data/SqlDataProvider.php 会先用正则把 SQL 中已有的ORDER BY段提取为Expression前置再调用buildOrderByAndLimit()拼装排序与分页保证自定义 SQL 与 Sort 排序共存。7.4 视图层输出无论哪种数据提供者视图层输出排序链接的方式一致与 framework/data/Sort.php 的文档示例相同// 展示分别指向按 name 和 age 排序的链接 echo $sort-link(name) . | . $sort-link(age); foreach ($models as $model) { // 渲染 $model }结合 GridView 时只需在数据提供者中配置sortGridView 的列头即可自动生成带data-sort属性与asc/desc样式类的排序链接。八、测试验证Sort 的契约行为仓库测试 tests/framework/data/SortTest.php 是对上述行为的权威背书关键用例包括testGetOrders/testGetAttributeOrders验证多属性排序下orders展开为列映射、attributeOrders保留属性级方向以及单属性模式下只保留第一个属性。testGetAttributeOrder验证单属性方向查询未知属性返回null。testSetAttributeOrders验证手动注入排序方向时的校验行为——enableMultiSort false时只保留第一个校验开启时未知属性会被剔除$validate false则原样保留。testCreateUrl/testLinkWithParams/testLinkWithoutParams验证生成 URL 的编码结果、asc/descCSS 类、data-sort属性以及defaultOrder对链接状态的影响。testGetExpressionOrders验证直接排序表达式如 PostgreSQL 的NULLS FIRST原样进入orders。这些用例同时也是理解Sort行为边界的速查手册。九、小结yii\data\Sort是 Yii 2 输出层排序功能的基石通过attributes声明排序白名单orders驱动查询、link()/createUrl()驱动交互sortParam/defaultOrder/enableMultiSort控制请求解析与默认行为并且天然与 ActiveDataProvider、ArrayDataProvider、SqlDataProvider 以及 GridView 协同工作。掌握本文内容你就能在任意 Yii 2 项目中快速实现安全、可扩展、体验良好的多列排序功能。赞分享后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载相关推荐Yii 2 数据排序实战深入解析 yii\data\Sort 的属性声明、排序链接与 DataProvider 集成Yii 2 数据排序实战深入解析 yii\data\Sort 的属性声明、排序链接与 DataProvider 集成 Yii 2 在 yii\data\Sor后端Web框架Yii 2 数据排序实战yii\data\Sort 对象从入门到源码级解析Yii 2 数据排序实战yii\data\Sort 对象从入门到源码级解析 本篇技术指南以官方文档《排序》 docs/guide zh CN/output后端Web框架Yii 2 排序实战基于 yii\data\Sort 实现用户可控的数据排序Yii 2 排序实战基于 yii\data\Sort 实现用户可控的数据排序 本文以 Yii 2 框架的官方指南 docs/guide ru/output s后端Web框架上一篇secGear本地证明与远程证明对比分析构建多层安全验证体系下一篇QEMU串口和控制台配置如何通过串口访问虚拟机控制台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

vcard4cj源码剖析:saveToVCF如何写出标准CRLF换行的VCF文件

vcard4cj源码剖析:saveToVCF如何写出标准CRLF换行的VCF文件

vcard4cj源码剖析:saveToVCF如何写出标准CRLF换行的VCF文件 【免费下载链接】vcard4cj 一个电子名片标准格式(.vcf文件)解析库 项目地址: https://gitcode.com/Cangjie-TPC/vcard4cj vcard4cj 是一个 Cangjie 语言编写的 VCF&#xff…

2026/9/24 16:22:27 阅读更多 →
Apache Thrift Java 教程实战:从编译运行到源码级原理剖析

Apache Thrift Java 教程实战:从编译运行到源码级原理剖析

后端微服务API设计 【免费下载链接】thrift Apache Thrift 项目地址: https://gitcode.com/gh_mirrors/thrift2/thrift 点击查看 免费下载 本指南围绕 tutorial/java/README.md 展开,完整讲解 Apache Thrift Java 教程的运行流程:如何编译 J…

2026/9/24 16:22:27 阅读更多 →
C语言相关知识:

C语言相关知识:

一.如何使用根号&#xff1a;引入这个头文件 #include <math.h> double a 2;double b sqrt(a); 此时b1.414214.........在输出开根号的数时&#xff0c;通常需要控制小数的位数&#xff0c;可以这样操作&#xff1a;printf("%nlf",b);n为小数…

2026/9/24 16:22:27 阅读更多 →

最新新闻

PHPStan 错误标识 requireExtends.deprecatedClass 全解析:当 @phpstan-require-extends 引用了已废弃的类

PHPStan 错误标识 requireExtends.deprecatedClass 全解析:当 @phpstan-require-extends 引用了已废弃的类

开发工具代码质量静态分析 【免费下载链接】phpstan PHP Static Analysis Tool - discover bugs in your code without running it! 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ph/phpstan 点击查看 免费下载 requireExtends.deprecatedClass 是 PHPStan 在 phpsta…

2026/9/24 16:56:04 阅读更多 →
loop-action:在 GitHub Actions 中安全执行自治 Agent 的 Composite Action 实战指南

loop-action:在 GitHub Actions 中安全执行自治 Agent 的 Composite Action 实战指南

人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务 【免费下载链接】loop-engineering Practical patterns, starters & CLI tools for loop engineering with AI coding agents. Design systems that prompt and orchestrate agents (inspired by Addy Osmani and …

2026/9/24 16:56:04 阅读更多 →
Comp AI CRM 图标设计工程指南:让图标在界面中自然安放的细节法则

Comp AI CRM 图标设计工程指南:让图标在界面中自然安放的细节法则

后端前端CRM人工智能AI Agent 【免费下载链接】crm Comp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/crm48/crm 点击查看 免费下载 本文以仓库内 .agents/skills/better-ui/icons.md 设…

2026/9/24 16:56:04 阅读更多 →
深入解析 Go 语言 YAML 处理库 gopkg.in/yaml.v3:在 wandb 中的实际应用与 API 全指南

深入解析 Go 语言 YAML 处理库 gopkg.in/yaml.v3:在 wandb 中的实际应用与 API 全指南

机器学习深度学习数据可视化可观测性 【免费下载链接】wandb The AI developer platform. Use Weights & Biases to train and fine-tune models, and manage models from experimentation to production. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/wa/wandb 点…

2026/9/24 16:56:04 阅读更多 →
RookieAI_yolov8是什么:基于YOLOv8的FPS游戏AI自瞄工具完整入门指南

RookieAI_yolov8是什么:基于YOLOv8的FPS游戏AI自瞄工具完整入门指南

RookieAI_yolov8是什么&#xff1a;基于YOLOv8的FPS游戏AI自瞄工具完整入门指南 【免费下载链接】RookieAI_yolov8 基于yolov8实现的AI自瞄项目 AI self-aiming project based on yolov8 项目地址: https://gitcode.com/gh_mirrors/ro/RookieAI_yolov8 RookieAI_yolov8 …

2026/9/24 16:56:04 阅读更多 →
Hermes 语义分析:基于 hermes_estree 的 JavaScript 名称解析与作用域分析模块深度解析

Hermes 语义分析:基于 hermes_estree 的 JavaScript 名称解析与作用域分析模块深度解析

语言运行时编译器移动开发 【免费下载链接】hermes A JavaScript engine optimized for running React Native. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/hermes/hermes 点击查看 免费下载 导读 hermes_semantic_analysis 是 Hermes 项目中用 Rust 实现的 JavaS…

2026/9/24 16:55:04 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源&#xff0c;围绕YOLOv8实现渔船作业监控系统&#xff0c;可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件&#xff0c;约24.21MB&#xff0c;以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介&#xff1a;一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码&#xff0c;针对计算机相关专业正在做毕设或需要项目实战的学习者&#xff0c;可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过&#xff0c;可直接运行&#xff0c;覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住&#xff0c;是在一个老旧的WinForms模块里&#xff1a;几十个类依赖PropertyChanged通知&#xff0c;运行时反射读属性、发通知&#xff0c;每次启动慢半拍不说&#xff0c;一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事&#xff1a;用Flutter给OpenHarmony做一款游戏集合类的App&#xff0c;说白了就是把若干小游戏塞进一个壳里&#xff0c;用统一入口分发。这个方向本身不算新鲜&#xff0c;真正让我花了不少心思的&#xff0c;是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档&#xff0c;最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事&#xff1a;今天在表后面多加了两个空白行&#xff0c;明天给客户交稿前发现整个章节的编号全部错位&#xff0c;光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年&#xff0c;说实话&#xff0c;第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年&#xff0c;流量惨淡、功能臃肿、代码自己都懒得看第二遍之后&#xff0c;我才慢慢琢磨明白一个道理&#xff1a;第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践&#xff1a;原型怎样变成可用功能分类&#xff1a;[AI/大模型]细分主题&#xff1a;AI 增强型 CI/CD 流水线自动化与 GitOps 实践&#xff1a;Agent 工作流、工具调用与任务拆解&#xff1a;从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战&#xff1a;复盘记录怎样真正派上用场分类&#xff1a;[工程技术]细分主题&#xff1a;Kubernetes 生产环境运维与排障实战&#xff1a;可复制的项目复盘模板与决策记录大部分团队的事故复盘报告&#xff0c;最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理&#xff1a;核心链路应该先拆哪一步分类&#xff1a;[工程技术]细分主题&#xff1a;Docker 容器化技术与镜像安全管理&#xff1a;核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用&#xff08;包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →