文書化されていない変更またはPHP 5.4および関数のオーバーロード

どうでしたか


少し前に、PHP 5.4に移行したときに発生した問題に遭遇しました。 タスクは、ネイティブ機能を使用した機能をテストすることでした。 ちなみに、 Fumockerはこのタスクに対応しており、テストの組み込み関数を再定義できます。 私は一連のテストを作成し、ローカルで実行しました。 すべてのテストが成功しました。 いいね! タスクは完了し、プロジェクトをtravis-ciに追加するまで完全に満足していました。 そして? PHP 5.4ではビルドが壊れていましたが、5.3ではすべてが緑色になりました。



5.3と5.4の間では、オーバーロード関数に違いがあるはずだと思いました。



率直に言って、これまでphp 5.4リリースの説明にこの違いに関する情報を見つけたことがありません。 したがって、まず、Googleを拷問に行きました。 しかし、Googleは明確な答えを出すことができませんでした。 私が見つけたのは、メソッドのオーバーロードだけでした。 これにより、コードの実験を開始しました。



さあ、始めましょうか?


最初の欲求は、状況を再現するためのサンドボックスを作成することでした。 これを行うために、組み込みの範囲関数を使用する単純なクラスを作成しました。

<?php // MyClass.php namespace MyNamespace; class MyClass { public function makeMeRange() { return range(1,3); } }
      
      







同じ名前のスコープ内でこの関数をオーバーライドした別のファイル:

 <?php // MyNamespaceFunctions.php namespace MyNamespace; function range($low, $high, $step = null) { return 'Overridden'; }
      
      







次に、最初のMyClassオブジェクトを作成する前に、クラスと関数の定義にファイルを含めるとどうなるかを考えました。

 <?php // main.php include_once("MyClass.php"); include_once("MyNamespaceFunctions.php"); use MyNamespace\MyClass; $my_obj = new MyClass(); echo $my_obj->makeMeRange();
      
      







この場合、動作は2つのバージョンで同じです。

 $ php54 main.php Overridden
      
      





 $ php53 main.php Overridden
      
      







しかし、 MyClassの最初のインスタンスを作成した後に、ファイルに関数を添付するとどうなりますか?

 <?php include_once("MyClass.php"); use MyNamespace\MyClass; $my_obj = new MyClass(); include_once("MyNamespaceFunctions.php"); $other_obj = new MyClass(); echo $my_obj->makeMeRange();
      
      







それでも違いはありません:

 $ php54 main.php Overridden
      
      





 $ php53 main.php Overridden
      
      







両面動作の理由を見つける最後の機会が残っています-同じ関数をオーバーライドしてファイルをインクルードする前に関数を呼び出してみてください:

 <?php include_once("MyClass.php"); use MyNamespace\MyClass; $my_obj = new MyClass(); $my_obj->makeMeRange(); include_once("MyNamespaceFunctions.php"); $other_obj = new MyClass(); echo $other_obj->makeMeRange();
      
      







うん! ガッチャ!

 $ php54 main.php PHP Notice: Array to string conversion in /Volumes/Projects/php-experiments/ …
      
      





 $ php53 main.php Overridden
      
      







そして最後の最後の実験(私は約束します):

 <?php include_once("MyClass.php"); use MyNamespace\MyClass; $my_obj = new MyClass(); $my_obj->makeMeRange(); include_once("MyNamespaceFunctions.php"); echo $my_obj->makeMeRange();
      
      







5.3と5.4の間の関数のオーバーロードの違いを確認します。

 $ php54 main.php PHP Notice: Array to string conversion in /Volumes/Projects/php-experiments/ …
      
      





 $ php53 main.php Overridden
      
      







最後に


関数が以前に再定義されていない場合、php 5.3では、スクリプトの実行中にいつでも関数をオーバーライドできます。 同時にphp 5.4は、コードのどこかで最初に使用されたバージョンの関数のみを使用します。



この記事では、説明した問題に加えて、長年の問題である「ドキュメントの関連性」を提起しています。 はい、私たちは自己の責任において欠陥のある文書を使用せざるを得ません。 私の意見では、これは私たちの頭の中に恥ずべきことです。



PS:説明した動作をテストするためにリポジトリを作成しました。 自分で確認したい場合は、リポジトリを複製し、phpunitを使用してテストを実行するだけです。



PSS:また、 bugs.php.netにオープンチケット#63201もあります。 この問題への参加は大歓迎です!



All Articles