この記事で挙動を確認した際の PHP のバージョンは 8.1.0 です。GitHubのソースコードをざっくり見た感じもっと古いバージョンでも同様の挙動をしてくれそうです。
普通に次のコードを書いて実行すると関数を再宣言できないというエラーになります。
<?php function strcmp() { echo 'call my strcmp'; } strcmp(); // Fatal error: Cannot redeclare strcmp() in C:\fakepath\tmp.php on line 3
しかしこれを正常に実行させる方法が PHP にはあります。使うのは php.ini で設定可能な項目の一つであるdisable_functions
です。
PHP: コア php.ini ディレクティブに関する説明 – Manual#disable_functions
これはその名の通り関数を無効化します。この設定を用いて次の様な php.ini を作ると既存の strcmp 関数をなかったことにできます(strcmp を使おうとすると undefined function strcmp() とエラーが出力される状態になります)。
disable_functions="strcmp" ; 複数の関数を登録するときは","で区切ります ; 半角スペースが入っても問題なく読み込まれます ; 存在しない関数名を含めても問題なく読み込まれます ; disable_functions=" strcmp ,file_put_contents, hi "
この php.ini を読ませた PHP においては自作の strcmp 関数の宣言と使用が認められ、次スクリーンショットの様になります。
例では関数の無効化のみを行いましたがdisable_classes
で同様の設定をすると PHP 組み込みの内部クラス(DateTime など)を無効化できます。
PHP: コア php.ini ディレクティブに関する説明 – Manual#disable_classes
こちらは挙動が少々複雑です。具体的には次です。
; php.ini disable_classes="DateTime"
<?php // 定数は有効時同様に使えます // Y-m-d\TH:i:sP echo DateTime::ATOM . "\n"; // インスタンス化する際に警告が発生します // Warning: DateTime() has been disabled for security reasons in xxx $d = new DateTime(); // 無効化されたクラスのインスタンスの中身は空のオブジェクトです // object(DateTime)#1 (0) { // } var_dump($d); // 無効化状態でも再宣言扱いとなって致命的なエラーとなります // Fatal error: Cannot declare class DateTime, because the name is already in use in xxx class DateTime { }
正直、使うことはそうそうない機能です。あえて挙げるならば、レンタルサーバーやオンラインエディタなどで PHP 実行環境を他人に渡す際に exec をはじめとした脆弱性のきっかけになりやすい機能をあらかじめ塞ぐ、iconv などの実行環境に依存する関数のモックを作る、あたりでしょうか。