Runkit 1.0.4の新機能:PHP 5.6+、あらゆる場所でのクロージャー、さらに12の新機能

PHP用Runkit 1.0.4がリリースされました!



待望の新しいメガリリースで、すべてのRunkitユーザーにおめでとうございます! Runkitを常に使用しており、その機能、履歴、および開発に精通している場合は、すぐにリリース1.0.4の変更説明に進むことができます。 いずれにせよ、私は記事全体を読むことを提案します。





Runkitとは何ですか?



RunkitはPHP言語の拡張機能であり、この言語の観点からは不可能なことを実行できます。 拡張機能は3つの部分で構成されています。



ランタイム操作



Runkit機能の最初で最大の部分を使用すると、動的に(PHPプログラムの実行中に)PHP言語自体によって動的変更が提供されないエンティティをコピー、変更、削除できます。



Runkitを使用すると、既存の関数(言語に組み込まれているものを含む)をコピー、再定義、削除したり、クラスを別のクラスの子孫にしたり、すべてのコンテンツを継承したり(runkit_class_adopt)、継承したコンテンツを削除してクラスを親から切り離したり(runkit_class_emancipate)できます。 また、既存のクラスのメソッドを追加、コピー、オーバーライド、および削除し、それらのプロパティを追加および削除できます。 さらに、Runkitでは、以前に定義された定数をオーバーライドおよび削除できます。



Runkit_sandbox



機能の2番目に大きい部分は、Runkit_Sandboxサンドボックスです。 それらは、隔離された環境でPHPのプログラムの一部を実行することを可能にします。 各サンドボックスは、safe_mode、safe_mode_gid、safe_mode_include_dir、open_basedir、allow_url_fopen、disable_functions、disable_classesなどの独自のPHPセキュリティ設定を持つことができます。 さらに、各サンドボックスは独自のRunkit機能を独自の方法で構成できます。独自のスーパーグローバル変数を配置し(以下で説明します)、組み込み関数の変更を禁止します。



サンドボックスは、PHPファイルを含めることができます(include()、include_once()、require()、require_once()を介して)、内部で関数を呼び出し、任意のPHPコードを実行し、内部変数の値を出力し、作業を完了します。 さらに、サンドボックスの出力をインターセプトして処理する関数を指定できます。



サンドボックス内で、Runkit_Sandbox_Parentアンチサンドボックスオブジェクトを作成して、サンドボックスを親環境に関連付けることもできます。 「アンチサンドボックス」の機能は「サンドボックス」の機能に非常に似ていますが、セキュリティ上の理由から、「サンドボックス」の作成時に外部環境と接続する各機能を明示的に有効にする必要があります。



スーパーグローバル



Runkitでは、新しいスーパーグローバル変数をPHPに追加することもできます。 このような変数を追加するには、PHP構成ファイル内のrunkit.superglobalプロパティに名前をコンマでリストするだけで十分です。



その他



機能の3つの主要な部分に加えて、Runkitには、PHPコードの構文(runkit_lintおよびrunkit_lint_file)をチェックするツールと、includeのようなPHPファイルをインポートできるが、このファイルのすべてのグローバルコードを無視できるrunkit_import関数もあります。 フラグに応じて、runkit_importは関数またはクラス(全体または一部)をインポートし、既存のものをオーバーライドまたは保存できます。



Runkitが必要な理由



Runkitは、PHPプログラマーがさまざまな問題を解決するのに役立ちます。 いくつかの基本的なものについてお話します。



他の人のプログラムにパッチを当てる



サードパーティのライブラリ(またはフレームワーク)を使用しており、ある時点でその動作を変更する必要があると想像してください。 ただし、変更する必要があるコードは、ライブラリクラスの1つのprivateメソッドにあります。 明らかな解決策は、このメソッドを含むファイルを編集することです。 これは有効なソリューションですが、ライブラリを更新するたびにパッチを適用する必要があるため、ライブラリコードが変更され、更新が面倒な作業になります。 別の解決策は、Runkitを使用して関心のあるメソッドをオーバーライドすることです。これは、runkit_method_redefine関数の1回の呼び出しで行われます。 プログラムに既に存在する関数(runkit_function_redefine)と定数(runkit_constant_redefine)を再定義するための同様のソリューションがあります。 実行時のプログラムコードの同様の変更は、「モンキーパッチ」と呼ばれます。 専門のオンラインフォーラムでは、WordPress、1C-Bitrix、CodeIngniter、LaravelなどのRunkitライブラリの助けを借りて、パッチを適用するためのさまざまなレシピを見つけることができます。 いくつかの問題を解決するには、PHP言語自体に組み込まれている関数を置き換えると便利です。また、Runkitでもこれを実行できます。



カスタムスクリプトを実行するための分離環境



Runkit_Sandboxは、サンドボックスを使用して、カスタムコードを実行するための環境を作成することがよくあります。 適切に設定すると、これによりメインシステムからユーザーコードを分離できます。 最も単純な形式では、次のようになります。



$options = […]; $sandbox = new Runkit_Sandbox($options); $sandbox->ini_set(…); $sandbox->eval($code);
      
      





その他のユースケース



runkitを使用すると、たとえばphpdaemon( habrahabr.ru/post/104811を参照)のように、プログラムコードの更新をその場で整理することもできます。



単体テスト



関数とメソッドをオーバーライドするRunkitの機能は、PHPで単体テストを作成するときに非常に役立ちます。 Runkitを使用すると、テスト対象のコードのアーキテクチャが依存関係の注入をサポートしていない場合でも、テスト実行中にテストダブル(スタブまたは「スパイ」)を作成することが簡単になります。 単体テストのコンテキストでスタブのPHPメソッドおよび関数の置換を実装する既製のライブラリがあります(たとえば、 ytestphpspyなど)。 適切なライブラリを使用すると、驚くほど単純なテストを取得できます(たとえば、 こちらを参照 )。



Runkitの歴史



開始する



Runkitは2005年にSarah Golemonによって作成されました。 最新の著者のリリース(バージョン0.9)は06.06.06にリリースされました。 2006年10月、サラはバージョン1.0をリリースせずに拡張機能のサポートを停止しました。 当時、Runkitには、定数、関数、メソッド、runkit_import、クラスにプロパティを追加する関数、構文チェック関数、サンドボックス、スーパーグローバル変数を操作するための関数が含まれていました。 php.net Webサイト( http://php.net/runkit )のドキュメントはバージョン0.7を中心にフリーズしたため、サラ自身が作成した機能の一部についてもまだ説明していません。 さらに、このドキュメントでは、Runkitのすべての機能は実験的と呼ばれています。これは2006年に関連していましたが、現在はまったく間違っています。



辞退



2006年10月から2009年10月まで、誰も拡張機能をサポートせず、PHP言語は前進しました。そのため、PHPコミュニティのメンバーによる編集にもかかわらず、RunkitはPHP 5.2で既に不安定であり、セグメンテーションエラーを引き起こしました。



復活



2009年10月に、Runkitの修復を開始し、 https://github.com/zenovich/runkitで開発しました。 この間にリリースされたリリースとそれらに含まれる変更について説明します。



リリース1.0.0(2010年4月1日)



実際、このリリースは決して起こらなかった、架空のものです:)。 バージョン0.9のリリース後、1.0.1のリリース前のすべてのコミュニティ編集が含まれます。



リリース1.0.1(2010年10月3日)



2006年以降のRunkitの最初の真のリリース。 現在、Runkitは5.3までのPHPのすべてのバージョンをサポートしています。 PHPのクラッシュを引き起こすものを含む、10を超える重大なバグが修正されました。 主なものは次のとおりです。



リリース1.0.1では、新しい定数RUNKIT_ACC_STATICを使用して静的メソッドを定義および変更する機能が追加されています。



 runkit_method_add('MyClass', 'newMethod', '$arg1, $arg2', '/* some code here*/', RUNKIT_ACC_STATIC);
      
      





静的クラスプロパティをインポートする機能も追加されました。 クラスをインポートすると、静的プロパティはデフォルトでコピーされますが、新しい定数RUNKIT_IMPORT_CLASS_STATIC_PROPSを使用してインポートを無効にできます。



 runkit_import('myfile.inc', RUNKIT_IMPORT_CLASSES); //    runkit_import('myfile.inc', RUNKIT_IMPORT_CLASSES & ~ RUNKIT_IMPORT_CLASS_STATIC_PROPS); //  ,       runkit_import('myfile.inc', RUNKIT_IMPORT_CLASS_STATIC_PROPS); //     
      
      





さらに、このリリースでは、Runkit_Sandbox :: call_user_func()を使用してサンドボックスにクロージャーを適用する機能が追加されました。



リリース1.0.2(2010年10月5日)



前のリリースのバグ修正。 PHP 5.3との互換性が改善されました。



リリース1.0.3(2012年1月2日)



runkit_method_renameを使用してメソッドの名前を変更するときの継承を修正しました。 Windows用の拡張機能のアセンブリが修正されました。



リリース1.0.4(2015年9月25日)



待望のメガリリース! PHP5の完全サポート(PHP 5.6まで)。



このリリースでは、Runkitの動作を安定させるために多くのことが行われました。テストは、PHPの各バージョンに対して4つのバージョンで実行されました。 ほとんどすべての変更について、新しいテストが追加されました。 これにより、膨大な数のエラーを特定して修正することができました。



重要な修正には次のものがあります。



合計で、リリースでは40以上(!!!)の重要な修正が行われました;それらの完全なリストはpackage.xmlファイルにあります。



次に、機能の主な変更点について説明します。



関数とメソッド


閉鎖


PHP 5.3以降では、関数runkit_function_add、runkit_function_redefine、runkit_method_add、runkit_method_redefineは、パラメーターとしてクロージャーをサポートするようになりました。 たとえば、以前に関数を再定義する場合、次の形式の式を記述する必要がありました。



 runkit_function_redefine('sprintf', '$s', 'return $s;');
      
      





evalを使用して文字列をバイトコードに変換しましたが、非常に遅いため、次のように記述できます。



 runkit_function_redefine('sprintf', function($s) {return $s;});
      
      





evalは同時に実行されず、そのようなコードの保守ははるかに簡単です-文字列リテラル内にプログラムの部分はもうありません! runkit_function_add、runkit_method_add、およびrunkit_method_redefine関数についても同じことが言えます。



魔法の方法


また、Runkitでは、マジックメソッド__get、__ set、__ isset、__ unset、__ clone、__ call、__ callStatic、serialize、unserialize、__ debugInfo、および__toStringを使用した操作が完全にサポートされるようになりました。 同じことは、コンストラクターとデストラクタにも当てはまります。最新の命名方法とPHP4スタイルの命名の両方です。



文書コメント


現在、古い構文を使用してメソッドと関数を追加またはオーバーライドするとき(新しい関数とその本体の引数が文字列で渡されるとき)、doc-commentsを指定できます。 この目的のために、関数runkit_function_add、runkit_function_redefine、runkit_method_addおよびrunkit_method_redefineには、新しいオプション(最後の順序)引数-doc_commentがあります。



 runkit_method_redefine('MyClass','myMethod', '$arg', 'return $arg', RUNKIT_ACC_PRIVATE, 'my doc_comment'); //     doc-comment' runkit_method_add('MyClass','myMethod2', '$arg', 'return $arg', NULL, 'my doc_comment2'); //     doc-comment'
      
      





(クロージャを介して)新しいスタイルで関数とメソッドを定義する場合、ドキュメントのコメントは、通常の関数を定義するときと同じ方法で、関数の本体のコメントを使用して指定できます。 両方の方法を組み合わせることができます-優先順位は、引数として渡されるdoc-commentです。 さらに、メソッドおよび関数を継承、コピー、および名前変更する際のドキュメントコメントの添付が修正されました。



参照による戻り値


新しい関数(またはメソッド)が参照によって値を返すように、関数とメソッドを追加および再定義する機能が追加されました。 古い構文(新しい関数とその本体の引数が文字列で渡される場合)を使用して指定された新しい関数が参照によって値を返すためには、関数runkit_function_add(またはrunkit_function_redefine)-return_ref-に値をTRUEで渡す必要があります。 例えば



 runkit_function_redefine('my_function', '$a', 'return $a;', TRUE); //    
      
      





メソッドが同じ方法で追加(または再定義)されると、RUNKIT_ACC_RETURN_REFERENCEビットが設定されたフラグ引数が使用されます。 例えば



 runkit_method_redefine('MyClass', 'myMethod', '$a', 'return $a;', RUNKIT_ACC_PROTECTED | RUNKIT_ACC_RETURN_REFERENCE); // protected-    
      
      





(クロージャを介して)新しい構文を使用して関数またはメソッドを定義する場合、これらのすべてのフラグは必要ありません-関数引数リストの前にアンパサンドを追加するだけです:



 runkit_function_redefine('my_function', function &($a) {return $a;}); //    
      
      





クラスのプロパティ


クラスプロパティを操作する内部実装が完全に再設計されました。 クラスプロパティの追加、削除、インポートが、子クラスに正しく影響するようになりました。 さらに、これらのアクションは、クラスおよびその子孫のオブジェクトに影響を与えることができるようになりました。 この効果を有効にするには、runkit_default_property_addおよびrunkit_default_property_redefine関数を呼び出すときに、flags引数にRUNKIT_OVERRIDE_OBJECTSビットを設定する必要があります。 例えば



 runkit_default_property_add('MyClass', 'newProperty', 'value'); //         runkit_default_property_add('MyClass', 'newProperty', 'value', RUNKIT_OVERRIDE_OBJECTS); //        -,     
      
      





クラスプロパティのインポートについても同じことが言えます。



 runkit_import('myfile.inc', RUNKIT_IMPORT_CLASS_PROPS); //   ,         runkit_import('myfile.inc', RUNKIT_IMPORT_CLASS_PROPS | RUNKIT_IMPORT_OVERRIDE); //   ,   ,     runkit_import('myfile.inc', RUNKIT_IMPORT_CLASS_PROPS | RUNKIT_IMPORT_OVERRIDE | RUNKIT_OVERRIDE_OBJECTS); //   ,        
      
      





さらに、クラスからプロパティを削除するための新しいrunkit_default_property_remove()関数が追加されました。 クラスからだけでなく、オブジェクトからもプロパティを削除するために、runkit_default_property_remove関数には3番目のオプションパラメータがあります。



 runkit_default_property_remove('MyClass', 'myProperty'); //    ,      runkit_default_property_remove('MyClass', 'myProperty', TRUE); //        
      
      





また、クラスプロパティを追加およびオーバーライドするときに、スカラー値だけでなく配列も使用できるようになりました。



クラス


以前は、関数runkit_class_adoptおよびrunkit_class_emancipateは、クラスの内容を変更しましたが、それらの階層に影響しませんでした(つまり、runkit_class_adoptを適用した後、クラスには正式に親がなく、runkit_class_emancipateの後も親は残りました)。 これは現在修正されています。



エンティティ名と名前空間のケース


定数、関数、メソッド、およびプロパティの操作は、名前空間を完全にサポートするようになりました。 Runkitは、作成するプロパティ、クラス、メソッド、および関数の名前を下げることも停止しました(以前と同様)。



追加のサンドボックスセキュリティ


Runkit_Sandboxサンドボックスの場合、INI設定allow_url_includeを無効にできるようになりました。 また、プラットフォームに関係なく、open_basedir構成はパスリストをサポートします(以前は、1つのパスしか入力できませんでした)。



更新情報


Runkitの更新がはるかに簡単になりました。 これは、 公式のpecl.php.netチャネルを介して、すべてのPECLユーザーに対して通常の方法で実行できます。 Runkitの最新リリースをインストールするには、ダイヤルするだけです



 pecl install runkit
      
      





さらに、すべてのリリースアーカイブがhttp://pecl.php.net/runkitで入手できるようになりました。



おわりに



現在、Runkitは、単体テストやその他の多くのタスクのために、世界中の多くの有名な企業やプロジェクトで使用されています。 彼には素晴らしい未来が待っていると確信しています。 プロジェクトページgithub.com/zenovich/runkitから、またはphpinfo()から直接クリックすることで、寄付ができるようになりました。



ありがとうございます!



All Articles