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

0st*_*ne0 19 php alias backwards-compatibility php-8

在测试我的脚本是否与兼容时,我遇到了以下代码:

function getDir($a, $o = 2) {
    $d = Floor($a / $o);
    return ($d % 2 === 0);
}
Run Code Online (Sandbox Code Playgroud)

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

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

3v4l.org


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

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

php-src 第 709 行

问题

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

Sar*_*ara 14

简短回答:哎呀

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

目前,我计划在 8.0.5 之前将其消失,抱歉打扰了,感谢 Chris 提交关于此的错误报告:https : //bugs.php.net/bug.php? id =80914


IMS*_*SoP 11

结果证明这比我预期的要有趣得多。

简短的回答是 getdir() 在 PHP 8.0.0 中确实是新的,但这是一个错误,它可能会在 8.0.4 或 8.0.5 中被删除。

有趣的是,getdir() 实际上不是别名,而是函数内部的真实名称;只是在 8.0 之前,它只能通过其别名 dir() 访问。为了解释这一点,我们必须追溯到 20 多年前……


目录()在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}
};
Run Code Online (Sandbox Code Playgroud)

不久之后,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}
};
Run Code Online (Sandbox Code Playgroud)

没有目标的别名实际上没有意义(并且有一个 PHP_NAMED_FE 宏就是为了这个目的)但它有效,所以我想没有人注意到。

事实上,通过 PHP 5 和 PHP 7 的所有变化,它继续工作,基本相同的 C 代码行直到 7.4

PHP_FALIAS(dir,  getdir, arginfo_dir)
Run Code Online (Sandbox Code Playgroud)

然而,在 PHP 8 的工作期间,构建了一个系统来从 PHP“存根”生成内部函数信息。作为此存根的一部分,为所有函数别名添加了存根,而 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 {}
Run Code Online (Sandbox Code Playgroud)

然后用它重新生成 C 定义,最后getdir() 有自己的函数入口

ZEND_FE(getdir, arginfo_getdir)
ZEND_FALIAS(dir, getdir, arginfo_dir)
Run Code Online (Sandbox Code Playgroud)

这导致 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 版本中恢复。她还在这里发布了答案,因为我还没有。