athari / yalinqo
YaLinqo,PHP的对象LINQ库
v2.5.0
2023-07-11 15:51 UTC
README
功能
- 是.NET LINQ到PHP的最完整移植,增加了许多额外的方法。
- 懒加载评估、错误信息和其他LINQ原始行为。
- 基于所有方法的PHPDoc和在线参考,详细文档基于MSDN的原始LINQ文档。文章从原始LINQ文档改编。
- 100%单元测试覆盖率。
- 在功能齐全的LINQ移植(YaLinqo、Ginq、Pinq)中性能最佳,至少比最接近的竞争对手快2倍,请参阅性能测试。
- 回调函数可以指定为闭包(如
function ($v) { return $v; }
),PHP "函数指针"(可以是字符串如'strnatcmp'
或数组如array($object, 'methodName')
),使用各种语法的字符串 "lambdas"(如'"$k = $v"'
,'$v ==> $v+1'
,'($v, $k) ==> $v + $k'
,'($v, $k) ==> { return $v + $k; }'
)。 - 键与值一样重要。大多数回调函数接收键和值;可以同时对键和值应用转换;在可能的情况下,键在转换过程中永远不会丢失。
- 在整个代码中使用SPL接口
Iterator
、IteratorAggregate
等,并且可以与Enumerable互换使用。 - 避免冗余的集合类,所有地方都使用原生PHP数组。
- 支持Composer(Packagist上的包)。
- 无外部依赖。
实现的方法
由于名称是保留关键字,一些方法需要重命名。括号内给出原始方法名称。
- 生成:cycle、emptyEnum(空)、from、generate、toInfinity、toNegativeInfinity、matches、returnEnum(返回)、range、rangeDown、rangeTo、repeat、split;
- 投影和过滤:cast、ofType、select、selectMany、where;
- 排序:orderBy、orderByDescending、orderByDir、thenBy、thenByDescending、thenByDir;
- 连接和分组:groupJoin、join、groupBy;
- 聚合:aggregate、aggregateOrDefault、average、count、max、maxBy、min、minBy、sum;
- 集合:all、any、append、concat、contains、distinct、except、intersect、prepend、union;
- 分页:elementAt、elementAtOrDefault、first、firstOrDefault、firstOrFallback、last、lastOrDefault、lastOrFallback、single、singleOrDefault、singleOrFallback、indexOf、lastIndexOf、findIndex、findLastIndex、skip、skipWhile、take、takeWhile;
- 转换:toArray、toArrayDeep、toList、toListDeep、toDictionary、toJSON、toLookup、toKeys、toValues、toObject、toString;
- 操作:call(do)、each(forEach)、write、writeLine。
总共超过80个方法。
示例
处理示例数据
// Data $products = array( array('name' => 'Keyboard', 'catId' => 'hw', 'quantity' => 10, 'id' => 1), array('name' => 'Mouse', 'catId' => 'hw', 'quantity' => 20, 'id' => 2), array('name' => 'Monitor', 'catId' => 'hw', 'quantity' => 0, 'id' => 3), array('name' => 'Joystick', 'catId' => 'hw', 'quantity' => 15, 'id' => 4), array('name' => 'CPU', 'catId' => 'hw', 'quantity' => 15, 'id' => 5), array('name' => 'Motherboard', 'catId' => 'hw', 'quantity' => 11, 'id' => 6), array('name' => 'Windows', 'catId' => 'os', 'quantity' => 666, 'id' => 7), array('name' => 'Linux', 'catId' => 'os', 'quantity' => 666, 'id' => 8), array('name' => 'Mac', 'catId' => 'os', 'quantity' => 666, 'id' => 9), ); $categories = array( array('name' => 'Hardware', 'id' => 'hw'), array('name' => 'Operating systems', 'id' => 'os'), ); // Put products with non-zero quantity into matching categories; // sort categories by name; // sort products within categories by quantity descending, then by name. $result = from($categories) ->orderBy('$cat ==> $cat["name"]') ->groupJoin( from($products) ->where('$prod ==> $prod["quantity"] > 0') ->orderByDescending('$prod ==> $prod["quantity"]') ->thenBy('$prod ==> $prod["name"]'), '$cat ==> $cat["id"]', '$prod ==> $prod["catId"]', '($cat, $prods) ==> array( "name" => $cat["name"], "products" => $prods )' ); // Alternative shorter syntax using default variable names $result2 = from($categories) ->orderBy('$v["name"]') ->groupJoin( from($products) ->where('$v["quantity"] > 0') ->orderByDescending('$v["quantity"]') ->thenBy('$v["name"]'), '$v["id"]', '$v["catId"]', 'array( "name" => $v["name"], "products" => $e )' ); // Closure syntax, maximum support in IDEs, but verbose and hard to read $result3 = from($categories) ->orderBy(function ($cat) { return $cat['name']; }) ->groupJoin( from($products) ->where(function ($prod) { return $prod["quantity"] > 0; }) ->orderByDescending(function ($prod) { return $prod["quantity"]; }) ->thenBy(function ($prod) { return $prod["name"]; }), function ($cat) { return $cat["id"]; }, function ($prod) { return $prod["catId"]; }, function ($cat, $prods) { return array( "name" => $cat["name"], "products" => $prods ); } ); print_r($result->toArrayDeep());
输出(压缩后)
Array (
[hw] => Array (
[name] => Hardware
[products] => Array (
[0] => Array ( [name] => Mouse [catId] => hw [quantity] => 20 [id] => 2 )
[1] => Array ( [name] => CPU [catId] => hw [quantity] => 15 [id] => 5 )
[2] => Array ( [name] => Joystick [catId] => hw [quantity] => 15 [id] => 4 )
[3] => Array ( [name] => Motherboard [catId] => hw [quantity] => 11 [id] => 6 )
[4] => Array ( [name] => Keyboard [catId] => hw [quantity] => 10 [id] => 1 )
)
)
[os] => Array (
[name] => Operating systems
[products] => Array (
[0] => Array ( [name] => Linux [catId] => os [quantity] => 666 [id] => 8 )
[1] => Array ( [name] => Mac [catId] => os [quantity] => 666 [id] => 9 )
[2] => Array ( [name] => Windows [catId] => os [quantity] => 666 [id] => 7 )
)
)
)
需求
- 版本1(稳定版):PHP 5.3或更高版本。
- 版本2(稳定版):PHP 5.5或更高版本。
- 版本3(预览版):PHP 7.0或更高版本。
使用方法
添加到composer.json
{ "require": { "athari/yalinqo": "^2.0" } }
添加到您的PHP脚本中
require_once 'vendor/autoloader.php'; use \YaLinqo\Enumerable; // 'from' can be called as a static method or via a global function shortcut Enumerable::from(array(1, 2, 3)); from(array(1, 2, 3));
许可证
简化版BSD许可证
版权所有 © 2012–2018,亚历山大·普罗霍罗夫
保留所有权利。
链接
YaLinqo 文章
-
CodeProject (英文):
- LINQ for PHP 比较:YaLinqo, Ginq, Pinq —— 全功能 LINQ 端口的性能比较,附带一些额外信息。
-
Habrahabr (俄语):
- 旧 LINQ 库比较 —— 对 LINQ for PHP、Phinq、PHPLinq 和 Plinq 以及 Underscore.php 的比较。
- YaLinqo 1.0 带更新比较 —— 架构和设计决策的说明。
- YaLinqo 2.0 —— 转移到支持生成器的 PHP 5.5 及相关更改。
- LINQ for PHP:速度很重要 —— 全功能 LINQ 端口(YaLinqo、Ginq、Pinq)的性能比较。
-
其他 (英语):
- Tute Wall: 如何在 PHP 中使用 Linq by Mr. X —— 一系列文章,涵盖 YaLinqo 的基本用法。
相关项目
- linq.js —— JavaScript 的 LINQ。.NET LINQ 到 JavaScript 的唯一完整端口。
- Underscore.js —— JavaScript 的函数式编程库。与 LINQ 类似,但方法名称不同且没有懒加载。
- Underscore.php —— Underscore.js 到 PHP 的端口。
- RxPHP —— LINQ 的反应式(推送)对应物,Rx.NET 的端口。
- YaLinqoPerf —— 比较原始 PHP、数组函数、YaLinqo、带字符串 lambda 的 YaLinqo、Ginq、带属性访问器的 Ginq 和 Pinq 的性能测试集合。