まず典型的な例を見てみましょう。一部のサービス登録プロセスでは、サービスが特定のインターフェイスに準拠することを確認するために、開発者は次のコードを使用します。
<code> if(!is_a($ serviceinstance、myServiceInterface :: class)){throw new invalidargumentException( "サービスはmyServiceInterface"を実装する必要があります "); } </code>表面上、これにより、登録段階でのエラータイプの噴射が防止されるため、ランタイムエラーが回避されます。実際、このアプローチは、インターフェイス分離の保証です。しかし、ここに質問があります:手動でチェックする必要がありますか?
PHP 7から始めて、タイププロンプトは十分に強力です:
<code> function registerservice(myserviceinterface $ service){// ...} </code>この時点で、 MyServiceInterfaceと一致しないインスタンスを渡すと、PHP自体がTypeRrorを投げます。それで、私たちはまだis_a()でもう一度手動でそれをチェックする必要がありますか?
実際、それは必要ありません。コードが混合タイプを渡すことを許可しない限り、またはサービスインスタンスのソースが非常に不確実でない限り(リモートインスタンスインスタンスインジェクション、プラグインシステムの読み込みなど)、PHPのタイプのプロンプトメカニズムで十分です。
IS_A()の過剰使用は、いくつかの隠された問題をもたらします:
繰り返し検証:タイプシステムがチェックされており、メンテナンスの負担を増やすために手動で繰り返されます。
障害物の多型:一部の実装クラスは、特性または動的プロキシメソッドを使用してインスタンスを生成する場合があり、 IS_A()のチェックにより、違法なオブジェクトとして誤解される可能性があります。
コンテナロジックを冗長にする:容器の責任は、タイプの強制的な検証ではなく、依存関係を解析および注入することです。重い責任があまりにもカップリングに簡単につながる可能性があります。
is_a()が役に立たないという意味ではありません。次のシナリオではまだ役立ちます。
プラグインシステム:第三者が提供する拡張クラスをタイププロンプトを使用して制約できない場合、 IS_A()を使用して事前に失敗する可能性があります。
ダイナミックサービス登録:たとえば、構成ファイルを読んでサービスを動的にインスタンス化する場合、適切なIS_A()検証はセキュリティ上の理由で受け入れられます。
悪意のある注入を避ける:大規模なシステムでは、一部のモジュールが複数のチームによって維持される場合があり、最終防衛戦略としてIS_A()を使用することもボトムアップ戦略です。
通常のサービス登録ロジックでは、可能な限りネイティブタイプのプロンプト +自動依存噴射を使用することをお勧めします。コードをシンプルに保ち、責任を独身にします。コンテナの場合、オブジェクトを構築し、依存関係を注入し、ライフサイクルを解決できるのに十分であり、「警察をチェックする」責任を負う必要はありません。
動的チェックが本当に必要な場合は、 is_a()をツール関数にカプセル化し、次のような統一された方法で管理することをお勧めします。
<code> function assertimplements($ instance、string $ interface){if(!is_a($ instance、$ interface)){throw new invalidargumentexception( "インスタンスインターフェイス:$ interface"); }} </code>これにより、読みやすさが向上するだけでなく、カップリングも削減されます。