While testing if my php script is php-8 compatible, I got stuck on the following code:
function getDir($a, $o = 2) {
$d = Floor($a / $o);
return ($d % 2 === 0);
}
Prior to php-8, this worked fine, however, on php-8 it throws:
Fatal error: Cannot redeclare getDir()
3v4l.org
After searching for a while, I've found that php-8 introduced a new alias to dir()
:
/** @param resource $context */
function getdir(string $directory, $context = null): Directory|false {}
php-src line 709
dir()
doesn't mention the aliasShort answer: Whoopsie
Long answer: https://externals.io/message/113982
At the moment, I would plan on this being gone by 8.0.5 Sorry for the break, and thanks to Chris for filing a bug report abut this: https://bugs.php.net/bug.php?id=80914
This turned out to be a lot more interesting than I expected.
The short answer is that getdir() really is new in PHP 8.0.0, but this was a mistake, and it will probably be removed in 8.0.4 or 8.0.5.
The interesting part is that getdir() is not in fact an alias, but the real name of the function internally; it's just that until 8.0, it was only accessible via its alias, dir(). To explain that, we have to go back more than 20 years...
The dir() function was added in PHP 3.0. For whatever reason - perhaps a last-minute change of name - the C function that implemented it was called "php3_getdir" not "php3_dir". That didn't matter, because every function name was mapped explicitly, like this:
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}
};
Not long after, PHP 4 came along, and function definitions moved to using macros to match the C name to the PHP name. Since the name of the function and implementation didn't match, "dir" ended up labelled as an "alias"; but no extra entry was added for "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}
};
An alias without a target doesn't really make sense (and there was a PHP_NAMED_FE macro for just this purpose) but it worked, so I guess nobody noticed.
In fact, through all the changes of PHP 5 and PHP 7, it carried on working, with basically the same line of C code right up to 7.4.
PHP_FALIAS(dir, getdir, arginfo_dir)
During the work on PHP 8, however, a system was built to generate internal function information from PHP "stubs". As part of this stubs were added for all function aliases, and getdir() ended up with its own stub:
/** @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 {}
This was then used to re-generate the C definitions, and finally getdir() had its own function entry
ZEND_FE(getdir, arginfo_getdir)
ZEND_FALIAS(dir, getdir, arginfo_dir)
This caused getdir() to be a real built-in function name, and meant you couldn't have a function with the same name.
From there, four things have happened:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With