PHP 需要自己的 ES6

2025-06-08

PHP 需要自己的 ES6

我对 PHP 又爱又恨。在过去的 15 多年里,我用 PHP 编写过各种类型的代码,从网站模板、WordPress 到完整的 MVC 和 SPA 后端解决方案。

我读了 Bronson Dunbar 的文章“使用和学习 ReactJS 2 年,我学到了什么”,然后我停在了这里:

正如我们前面提到的,JavaScript 已经存在了一段时间,为了保持相关性,一些人决定是时候对其进行更新,这就是 ES6 诞生的时候。

Javascript 和 PHP 的发展历程颇有相似之处。它们都并非为如今的用途而生:1995 年,Brendan Eich 仅用 10 天时间编写了 Javascript 原型,为浏览器提供与 Netscape 的交互;而 Rasmus Lerdorf 则在 1994 年编写了 PHP,将其作为模板引擎。由于两者的流行,它们如今已演变成截然不同的语言。

过去几年(在克服了 Python 2->3 的痛苦之后),我一直在思考和谈论如何让 PHP 打破向后兼容性。我知道这不会发生,因为互联网的很大一部分都运行在 PHP 上,这会破坏一切。

因此,Bronson 的帖子给了我一些思考:也许我们不需要“新的 PHP”,也许我们需要ES6-for-PHP ——PHP 之上的一层,它允许我们解决问题并编写不同的 PHP,同时仍然保持底层兼容。

背景

我不是语言设计师,也不是那种在构建新编程语言中找到乐趣(也没有任何技能)的人。但我是一个梦想家,而且我可以梦想。

PHP 的一大痛点在于其标准库的不一致。这其实是一个特性,而非 bug。Rasmus Lerdorf 在创建 PHP 时,曾使用过不同类型的命名方案来平衡函数哈希

嗯,这里面还有其他因素在起作用。htmlspecialchars 是一个非常早期的函数。当时 PHP 的函数数量还不到 100 个,函数哈希机制是 strlen()。为了使函数名在不同长度的函数名之间获得良好的哈希分布,函数名的选取是经过精心设计的,以使其适合特定的长度范围。当时大约是 1994 年末,PHP 还只是我个人使用的工具,我并不太担心记不住那几个函数名。

但现在已经 2019 年了,还有很多 PHP 代码在编写中。如果我们能让它变得更有趣些会怎么样?(我喜欢写 Ruby 和 Ruby on Rails,DHH 的《Rails 教义》给了我很多启发。尤其是其中关于开发者幸福感的部分。)

那么我们应该做什么呢?

标准库命名的一致性层

从上面的引文可以看出,PHP 函数的命名是为了一个特定的目的:平衡哈希函数。这意味着随着标准库的不断增长,由于缺乏一致性,我们很难记住函数名的书写方式。

还有strpos但是str_rot13。还有php_uname但是phpversion。还有strtolower但是bin2hex。还有str_shuffle但是recode_string。你大概明白了。

因此,第一个行动计划是:创建一个一致且可预测的命名方案

将数组函数转换为数组方法

让我们来看一下。假设我们有一个数组,我们想先过滤这些值,然后再进行映射。在原生 PHP 中,我们会这样做:

array_map(
  function(number) {
    return number * 2;
  },
  array_filter(
    [1,2,3,4,5,6,7,8,9,10],
    function(number) {
      return number % 2 == 0;
    })
);

注意array_maphas 参数callback, arrayarray_filterhas 参数 的array, callback区别。我不知道为什么它们正好相反,但很多时候我记不住哪个是哪个,所以不得不求助于文档。而且由于嵌套很深,理解起来也很困难。

让我们看看如何让它变得更好。

array(1,2,3,4,5,6,7,8,9,10)
  ->filter(num -> num % 2 == 0)
  ->map(num -> num * 2)

将数组函数变成数组本身的方法,这样我们就可以链式调用。即使我们不想为匿名函数采用 ES6 风格的箭头函数,它也会让这段代码更容易理解和使用。

第二个行动计划:将array_函数变成数组方法,然后使其可链接

一种统治所有

那么排序怎么办呢?目前 PHP 的排序功能非常混乱。早在 2015 年,我就写过一篇博文,讲述了我当时的痛苦经历。引用我自己的话:

当然有 sort 。sort你不需要给 一个标志或参数来反转顺序,而是使用rsort。如果你想保持键=>值对的完整性,可以使用asort(自从我意外地用 代替 sort 以来,它一直给我带来很多困惑)和arsort。然后你可以使用ksort和 进行排序krsort。对于自然排序,有natsort和 (不区分大小写)natcasesort。当这些还不够时,你可以使用usortuasort和自定义比较函数。对于多维数组,uksort的命名不一致。array_multisort

如果我们只使用函数,并且可以与标志、键或自定义回调函数配合使用,会怎么样?sort()并且,排序时请提供一个返回数组的选项,而不是仅仅将排序作为副作用。我在大多数 PHP 项目中创建的第一个自定义函数就是一个sorted函数(借用自 Python 的名称),它使我能够更加函数式化。

第三个行动计划:统一排序

分离顺序数组和关联数组

你知道吗?PHP 只有关联数组。在 PHP 领域,它运行良好,但当你开始将其转换为 JSON 时,就会出现问题。我去年的另一篇博客文章重点介绍了这个问题。

如果使用数字、顺序和无序键对数组进行排序,则数组会从对象变为数组。如果使用数字、顺序和有序键对数组进行排序,则数组仍为数组。无论对非数字或非顺序数组进行何种操作,它仍为对象。

当我阅读或编写代码时,我应该能够更一致地推断出结果会是什么。使用array_valuesreset 来重置“曾经变成关联数组的顺序数组”的做法非常糟糕。

第四个行动计划:分离数组类型

结论

标准库的其他部分可能也能从“ES6 处理”中受益,但我使用 PHP 进行开发时遇到的最大痛点就是这些。

让我们回顾一下:

  1. 一致的命名
  2. 数组函数转化为可链式数组方法
  3. 仅此一种,不再有
  4. 两个数组比一个数组好

您希望通过 ES6-for-PHP 类型的解决方案增强 PHP 的哪些部分?

编辑于 2 月 9 日
如果您喜欢这个想法,请查看Khalyomedephp-next 项目

鏂囩珷鏉ユ簮锛�https://dev.to/hamatti/php-needs-its-own-es6-28fa
PREV
GitLab 加入了合法化歧视的行列。为什么没人谈论这件事?
NEXT
二分查找