事实证明,这比我预期的要有趣得多。
简短的回答是getdir()在PHP 8.0.0中确实是新的,但这是一个错误,它可能会在8.0.4或8.0.5中删除。
有趣的是,getdir() 实际上不是别名,而是函数内部的真实名称;只是在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 的所有更改,它继续工作,使用基本相同的 C 代码行直到 7.4。
PHP_FALIAS(dir, getdir, arginfo_dir)
然而,在 PHP 8 的工作中,构建了一个系统来从 PHP “stubs” 生成内部函数信息。作为此存根的一部分,为所有函数别名添加了存根,getdir() 最终具有自己的存根:
/** @param resource $context */
function getdir(string $directory, $context = null): Directory|false {}
/**
* @param resource|null $context
* @alias getdir
*/
function dir(string $directory, $context = null): Directory|false {}
然后用它来重新生成C定义,最后getdir()有自己的函数条目。
ZEND_FE(getdir, arginfo_getdir)
ZEND_FALIAS(dir, getdir, arginfo_dir)
这导致 getdir() 是一个真正的内置函数名称,并且意味着你不能有一个同名的函数。
从那里,发生了四件事: