48
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【PHP8.0】function_exists('getdir')がtrueになるんだけどなにこれ?

Last updated at Posted at 2021-04-12

まとめ

PHP8.0.0からPHP8.0.3までの間、getdir()という組み込み関数が存在する

Stack Overflow

PHP 8, function alias compatibility getdir()

こんなコードを書いたらなんかPHP8でエラーになるんだけど。

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

01.png

んで調べてみたらgetdirdirのエイリアスになってるみたい。
リリースノートにもエイリアスのこと全く書かれてないんだけど、なにこれ?

Answer 2

getdirPHP4時代の非常に古い関数なんだけど、最近仕様が変わったりしたのかね?

Answer 4

バグレポ出したよ。
getdirはケースセンシティブだったのがケースインセンシティブになったせいかね?

Answer 5

↑ちょっと待った、ケースセンシティブは関係ないんだ。
getdir()関数はこれまでずっと存在していなかったんだ。
でもソース中にはずっと存在していたんだ。
何か深刻なことが起こっているにちがいないぞ。

PHPメーリングリスト

Rowan Tommins

Stack Overflowの質問https://stackoverflow.com/q/66854655/157957およびそれに伴うバグレポートhttps://bugs.php.net/bug.php?id=80914において、不可解な現象が発生しました。
PHP8.0において、dir()関数の別名としてgetdir()が誤って追加されました。

実際はもっと奇妙なことになっています。
本当はgetdir()が正しい関数名で、dir()はそのエイリアスです。
しかし、PHP7.4まではエイリアスの方の関数しか存在しませんでした

PHP8.0においてはgetdir()は呼び出し可能な関数であり、そしてユーザが同名の関数を定義することはできません。

これは以下が原因だと思われます。

まず、dir()はPHP3から存在する関数であり、それはコンストラクタを使わないおかしなオブジェクトを生成します。

{"dir", php3_getdir, NULL},

PHPの関数名がCの関数名と一致しないため、PHP4のエイリアス機能によって以下に置き換えられます。

PHP_FALIAS(dir, getdir, NULL)

しかし、これは実際にはエイリアスではありませんでした。
PHP_FEマクロにgetdirが登録されていなかったためです。
そのため、コードで実際に使用できる関数名はdirだけでした。

この状況は、PHP8でarginfoが追加されるまで続きました。
Matéはgetdir()にスタブが無いことに気が付き、それを追加してくれました。

そして20年の時を経て、ついにgetdir()に関数エントリが追加されたのです。

    ZEND_FE(getdir, arginfo_getdir)
    ZEND_FALIAS(dir, getdir, arginfo_dir)

問題は、これをバグとみなして元に戻すべきかということです。
答え合わせはおそらく20年前に行われるべきだったもので、公開されている関数名に合わせて内部名を変更すべきでしょう。

Sara Golemon

PHP_NAMED_FEってマクロは当時も存在してたのに、Zeevはどうしてそのマクロを使わなかったのでしょう。
1999年当時はZend Engine1の開発真っ最中だったからてんやわんやだったのかな。

私なら、この文書化されていない関数は、PHP8.0.0から8.0.3までに存在していたバグとして葬ります。

Rowan Tommins

異議はなかったので、プルリクエストを提出しました。
getdir()を削除し、dir()関数の内部名をdirにします。

感想

C素人なのでPHPのソース読むのつらい。

PHPの関数は、まず関数を定義して、その情報を別途インデックスに登録することで使用可能になります。
getdir()関数は、定義自体はずっと前から存在し、むしろdir()getdir()へのエイリアスという構造でした。
しかし、getdir()関数そのものはインデックスに登録されていなかったので、これまでずっと使えない状態でした。
PHP8実装に伴い気を利かせてソースを整理したら、その前世紀の遺物が意図せず現出してきたということです。

閉ざされていた古代遺跡が復活した感ありますね。

48
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?