anahkiasen / 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,如果你把数组转换为整数,它返回数组的大小等。
核心概念是:静态调用从其方法返回值,而链式调用更新它们正在工作的对象的价值。这意味着Underscore对象不会返回其值,直到你在它上面调用->obtain
方法——在此之前,你可以无限地链,它将保持为一个对象。例外是一些被认为是中断者的属性,它们将返回对象的价值。例如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存储库。当创建一个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
类,并想在你的类中有一个与Strings::length
完全不同意义的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
在GitHub上实际上还有一个Underscore.js到PHP的端口,在GitHub上——我第一次发现它是在看到它曾一度被用于Laravel 4时。我很快对代码的混乱、缺乏更新以及背后的1:1心态感到失望。
这个全新的Underscore.php并非直接将Underscore.js移植过来。它有时会省略与PHP开发者无关的方法,将其他方法重命名以符合他们更常用的术语,提供更丰富的语法,增加大量方法,并为未来可能添加的方法留出空间——而之前的移植则迅速将所有JS方法转换为PHP,然后就此结束。
如果你来自JavaScript并且对一些更改感到困惑,不要把所有责任都归咎于我,因为我试图把一切都搞乱。一个基本的例子是map
函数:在PHP中,它的含义完全不同,因为存在一个array_map
函数,基本上做了与JS中的__::invoke
相同的事情。所以现在的map
就是Arrays::each
。始终记住,这是首先为PHP开发者设计的,并且两个之间确实存在差异,以适应PHP中的常用术语。