trafficfox / underscore-php
Underscore.js 的 PHP 版本,已进行脱密处理
此包的官方仓库似乎已不存在,因此该包已被冻结。
Requires
- php: >=5.4.0
- doctrine/inflector: ^1.0
- patchwork/utf8: ^1.2
Requires (Dev)
- fabpot/php-cs-fixer: 2.0.*@dev
- phpunit/phpunit: ^4.6
README
PHP 操作工具集
首先:Underscore.php 并非 不是 Underscore.js 的 PHP 版本(好吧,我确实最开始是这样的)。它并不旨在直接移植其方法,而是更注重移植其理念。
它是一个完全的 PHP 操作工具集,其语法优雅,直接受到 Laravel 框架 的启发。那些著名的 __() 被方法名和类名取代,它们旨在像 Rails 一样阅读:Arrays::from($article)->sortBy('author')->toJSON()。
它提供了一百多种针对各种类型的方法:字符串、对象、数组、函数、整数等,并提供了解析类,帮助在类型之间进行转换。哦,还有,它一直在不断发展。最好的部分?它很好地封装了原生 PHP 函数,这意味着 Strings::replace 实际上是调用 str_replace 的动态调用,但具有允许链式调用和一致参数顺序的优点(Underscore 中的所有函数都将主题作为第一个参数,无论是什么)。
它既可以通过 Composer 独立使用,也可以作为 Laravel 框架的捆绑包使用。所以,你知道的,你真的没有任何借口。
安装 Underscore
要安装 Underscore.php,只需运行 composer require anahkiasen/underscore-php。请注意,Underscore 的类型类(Arrays/Strings 等)默认在 Types 文件夹中命名空间化,因此要使用 Arrays,您将执行以下操作
use Underscore\Types\Arrays;
使用 Underscore
它可以作为静态类和面向对象类使用,因此以下两种方式都是有效的
$array = array(1, 2, 3); // One-off calls to helpers Arrays::each($array, function($value) { return $value * $value; }) // Square the array Function::once($myFunction) // Only allow the function to be called once Number::paddingLeft(5, 5) // Returns '00005' Object::methods($myObject) // Return the object's methods Strings::length('foobar') // Returns 6 // Or chain calls with the 'from' method Arrays::from($array)->filter(...)->sort(...)->get(2) // Which does this in the background $array = new Arrays($array); $array->filter(...)->sort(...)->get(2)
对于那些怀念旧的 __() 的用户,提供了一个通用的 Underscore 类,它可以调用 Underscore.php 中的所有方法。为此,它会查找其已知的方法,并分析方法的主题(这意味着如果你执行 Underscore::contains('foobar', 'foo'),它会知道你寻找的不是 Arrays::contains)。
关于类型:需要注意的是,使用特定的类型类来创建 Underscore 存储库将转换提供主题的类型。比如说你有一个对象,并执行 new Arrays($myObject) - 这将对象转换为数组,并允许你使用 Arrays 方法。为此,Underscore 使用其 Parse 类的方法,大部分只是类型转换并返回(如这 (array) $object),但它有时也会走得更远,理解你想做什么:如果你将数组转换为字符串,它将将其转换为 JSON,如果你将数组转换为整数,它返回数组的长度等。
核心概念是这样的:静态调用从它们的方法返回值,而链式调用则更新它们正在工作的对象的值。这意味着在调用 ->obtain 方法之前,Underscore 对象不会返回它的值——在此之前,您可以无限地链,它将保持为一个对象。例外的是某些被认为是 中断者 的属性,它们将返回对象的值。例如 Arrays->get。
请注意,由于所有传递给 Underscore 的数据都转换为对象,您可以这样做,再加上链式方法的强大功能,这使得数据操作变得轻而易举。
$array = new Arrays(['foo' => 'bar']); echo $array->foo // Returns 'bar' $array->bis = 'ter' $array->obtain() // Returns array('foo' => 'bar', 'bis' => 'ter')
自定义 Underscore
Underscore.php 提供了扩展任何类以自定义函数的能力,所以尽情发挥。不要忘记,如果您认为您有一个任何人都可以享受的函数,请发起一个拉取请求,让大家都能享受到它!
Strings::extend('summary', function($string) { return Strings::limitWords($string, 10, '... — click to read more'); }); Strings::from($article->content)->summary()->title()
您还可以在提供的配置文件中将所有 Underscore 的方法赋予自定义别名。只需向 aliases 选项添加条目,键是别名,值是要指向的方法。
可扩展性
从面向对象的角度来看,Underscore.php 的类也是可扩展的。您可以使用 setSubject 方法(或者通过 $this->subject = 直接进行,前提是您在最后返回 $this)。当创建一个 Underscore 存储库时,默认情况下它的主题是一个空字符串,您可以通过在 getDefault 方法中返回任何您想要的来更改它。
class Users extends Arrays { public function getDefault() { return 'foobar'; } public function getUsers() { // Fetch data from anywhere return $this->setSubject($myArrayOfUsers); } } $users = new Users; // Users holds 'foobar' $users->getUsers()->sort('name')->clean()->toCSV() // Same as above Users::create()->getUsers()->sort('name')->clean()->toCSV()
重要的是不要对 Underscore 中存在的众多方法和扩展一个类型可能造成的危险感到恐慌:方法不是包含在类本身中,而是在方法存储库中。所以如果您扩展了 Strings 类并且想在您的类上拥有一个具有完全不同含义的 length 方法,它不会引起任何签名冲突或任何其他问题。
此外,请注意 Underscore 方法路由是动态的,所以如果您的主题是一个数组,中途变为字符串,Underscore 总会找到正确的类来调用,不管您最初扩展了什么。尽管如此,还是要跟踪您的主题:如果您的主题变为字符串,例如调用 ->map 将会返回错误。
调用原生方法
Underscore 本地扩展了 PHP,因此当上下文匹配时,它可以自动引用原始 PHP 函数。现在,PHP 本身没有很多约定,所以 Arrays:: 寻找 array_ 函数,Strings:: 寻找 str_ 以及一些其他硬编码的重定向,但仅此而已。显然,优势是它允许在许多其他单次使用的函数或仅通过引用工作的函数上进行链式操作。
Arrays::diff($array, $array2, $array3) // Calls `array_diff` Arrays::from($array)->diff($array2, $array3)->merge($array4) // Calls `array_diff` then `array_merge` on the result
文档
您可以在 存储库的 wiki 或 官方页面 中找到所有类和方法的详细摘要。更改日志可在 CHANGELOG 文件中找到。
关于 Underscore.php
实际上还有一个Underscore.js到PHP的移植版本,可以在GitHub上找到[链接](https://github.com/brianhaveri/Underscore.php) —— 我第一次发现它是因为看到它在Laravel 4上曾经被使用过。我很快就对代码的混乱、更新的缺乏以及背后的1:1思维模式感到失望。
这个重写的Underscore.php并不旨在直接移植Underscore.js。它有时会省略对PHP开发者不相关的函数,将其他函数重命名为更常见的术语,提供更丰富的语法,添加了很多新的函数,并且留出空间以便未来可以持续添加——而之前的移植版本则快速将所有JS函数重写为PHP,然后就没有然后了。
如果你来自JavaScript并且对一些变化感到困惑,不要把所有的责任都推到我身上,因为我尝试弄乱一切。一个基本的例子是map函数:在PHP中,它有完全不同的意义,因为存在一个array_map函数,基本上做了JS中的__::invoke做的事情。所以map现在是Arrays::each。始终记住,这是首先为PHP开发者设计的,两种语言之间确实存在差异,以适应PHP中的常用术语。