这事情比我预料的有趣多了。
简短回答是getdir()确实是PHP 8.0.0版才新增的,但这是个错误,很可能在8.0.4或8.0.5版中被移除。有趣的是,getdir()事实上并不是一个别名,而是函数内部的真实名称;只不过在PHP 8.0之前,它只能通过它的别名dir()来访问。要解释这一点,我们需要回到20多年前...
dir()函数是在PHP 3.0中添加的。由于某种原因 - 可能是最后一分钟更改名称 - 实现它的C函数被称为“php3_getdir”,而不是“php3_dir”。这并不重要,因为每个函数名都是显式映射的,像这样:
function_entry php3_dir_functions[] = {
{"opendir", php3_opendir, NULL},
{"closedir", php3_closedir, NULL},
{"chdir", php3_chdir, NULL},
{"rewinddir", php3_rewinddir, NULL},
{"readdir", php3_readdir, NULL},
{"dir", php3_getdir, NULL},
{NULL, NULL, NULL}
};
不久之后,PHP 4推出了,函数定义
转移到使用宏来匹配C名称和PHP名称。由于函数名称和实现名称不匹配,“dir”最终被标记为“别名”,但是没有为“getdir”添加额外的条目:
static zend_function_entry php_dir_functions[] = {
PHP_FE(opendir, NULL)
PHP_FE(closedir, NULL)
PHP_FE(chdir, NULL)
PHP_FE(rewinddir, NULL)
PHP_FE(readdir, NULL)
PHP_FALIAS(dir, getdir, NULL)
{NULL, NULL, NULL}
};
没有目标的别名没有实际意义(而且有一个 PHP_NAMED_FE 宏可以用于此目的),但它确实起作用,所以我猜没有人注意到。
事实上,在 PHP 5 和 PHP 7 的所有更改中,它都继续工作,并且在 7.4 版本中基本上使用相同的 C 代码行。
PHP_FALIAS(dir, getdir, arginfo_dir)
在开发PHP 8期间,建立了一个系统,从PHP“存根”生成内部函数信息。作为其中的一部分,
为所有函数别名添加了存根,getdir()最终拥有了
自己的存根。
function getdir(string $directory, $context = null): Directory|false {}
function dir(string $directory, $context = null): Directory|false {}
然后使用此工具重新生成了C语言定义,最终getdir()具有自己的函数入口
ZEND_FE(getdir, arginfo_getdir)
ZEND_FALIAS(dir, getdir, arginfo_dir)
这导致getdir()成为真正的内置函数名称,这意味着您不能使用相同名称的函数。
从那时起,发生了以下四件事:
- 2021年3月29日:0stone0发布了这个问题。
- Chris Haas试图查找问题,并在PHP错误跟踪器上打开了一份错误报告,认为该问题与大小写敏感性有关。他们还确认getdir()是basic_functions.stub.php中唯一不在手册中的别名。
- 2021年4月6日:我认为我将快速修复文档,但却对以上内容产生兴趣,并深入研究。我在PHP内部邮件列表上发布了我的发现,并比预期晚了一个小时去睡觉。
- Sara Golemon(PHP 8.0版本发布管理员之一)回复同意应将其视为Bug并在下一个8.0.x版中撤销。由于我没有回复,她还在这里发布了答案。
getdir
别名似乎非常古老(< PHP 5)https://github.com/php/php-src/blob/php-4.4.9/ext/standard/basic_functions.c#L714。我在 php 迁移指南中没有看到任何关于函数重新声明的通知,也许这是一个在 PHP 8 中修复的 bug。 - thehennyyfunction_exists('getdir')
,但可能只是在 PHP 8 的本地环境中测试过。感谢 @IMSoP 进一步调查此事。 - Chris Haas