mariosvasiliou / underscore_php
Underscore.js 的 PHP 版本,已进行编辑
Requires
- php: >=8.1.0
- doctrine/inflector: ^2.0
- symfony/polyfill-mbstring: ^v1.22.0
- symfony/string: ^v5.2.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.1
- phpunit/phpunit: ^9.5.10
- roave/security-advisories: dev-latest
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 mariosvasiliou/underscore_php。请注意,Underscore 的类型类(Arrays/Strings等)默认位于 Types 文件夹中命名空间内,所以使用 Arrays,你需要做以下操作
use Underscore\Types\Arrays;
使用 Underscore
它可以作为静态类和基于对象的基本类使用,因此以下两种用法都是有效的
$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' BaseObject::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 方法时才会返回其值——在此之前,你可以无限地链式调用,它将保持为对象。例外是某些被视为 breakers 的属性,将返回对象的值。一个例子是 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 允许您使用自定义函数扩展任何类,所以尽情发挥吧。如果您认为某个函数任何人都可以使用,请发起一个pull request,让大家都能享受到它!
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 { /** * @return string */public function getDefault(): string { return 'foobar'; } /** * @return mixed */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中存在的大量方法和扩展Type之一的危险感到恐慌:这些方法并不包含在类本身中,而是在方法仓库中。所以如果您扩展了Strings类,并且希望您的类上的length方法与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
要求
PHP 7.3、7.4、8.0使用版本2.x
PHP 8.1+使用版本3.x
文档
您可以在仓库的wiki或官方网站中找到所有类和方法的详细摘要。更改日志可在CHANGELOG文件中找到。
关于Underscore.php
在GitHub上实际上还有一个Underscore.js到PHP的端口—— 我第一次发现它是用于Laravel 4的时候。我很快对代码混乱、缺乏更新和它背后的1:1思维感到失望。
这个重新设计的Underscore.php并不旨在成为Underscore.js的直接端口。它有时省略了与PHP开发者不相关的函数,将其他函数重命名为更常见的术语,提供了更丰富的语法,添加了大量的方法,并为未来添加的方法留下了空间——而之前的端口迅速将所有JS方法转换为PHP,并就此结束。
如果您来自JavaScript并且对某些变化感到困惑,请不要把所有责任都归咎于我,因为我试图搞砸一切。一个基本的例子是 map 函数:在PHP中,它有完全不同的意义,因为存在一个 array_map 函数,基本上做的是JS中 __::invoke 的事情。所以 map 现在是 Arrays::each。请始终记住,这是首先为 PHP 开发者设计的,并且两者之间确实存在差异,以适应PHP中的常用术语。