PHP 8,函数别名兼容性 'getdir()'

2022-08-30 22:13:07

在测试我的脚本是否兼容时,我卡在了以下代码上:

function getDir($a, $o = 2) {
    $d = Floor($a / $o);
    return ($d % 2 === 0);
}

之前,这工作正常,但是,在 上,它会抛出:

致命错误:无法重新声明 getDir()

3v4l.org


搜索了一段时间后,我发现引入了一个新的别名:dir()

/** @param resource $context */
function getdir(string $directory, $context = null): Directory|false {}

php-src 行 709

问题

  • 我可以在不重命名函数的情况下让我的代码在上运行吗?
  • 是否有所有新函数别名的列表?

答案 1

简短的回答:哎呀

长答案:https://externals.io/message/113982

目前,我计划在8.0.5之前删除它 抱歉休息,并感谢Chris提交了一个错误报告,但这个:https://bugs.php.net/bug.php?id=80914


答案 2

事实证明,这比我预期的要有趣得多。

简短的回答是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() 是一个真正的内置函数名称,并且意味着你不能有一个同名的函数。


从那里,发生了四件事:

  • 2021年3月29日:0stone0发布了这个问题。
  • Chris Haas试图找出这个问题,并在PHP错误跟踪器上打开了一个错误,认为这个问题与区分大小写有关。他们还确认getdir()是basic_functions.stub中唯一的别名.php手册中没有。
  • 2021年4月6日:我以为我要做一个快速的文档修复,我产生了兴趣,并消失在上面的兔子洞里。我把我的发现发布到PHP内部邮件列表,比我预期的晚了一个小时上床睡觉。
  • Sara Golemon(PHP 8.0版本管理器之一)回复说,它应该被视为一个错误,并在下一个8.0.x版本中恢复。她还在这里发布了一个答案,因为我还没有。

推荐