web-dev-qa-db-ja.com

PHPで後方互換性を維持するためにclass_alias()を使用することの影響

シナリオ:数年前から存在しているオープンソースのPHPプロジェクトには、メインの名前空間にクラスが多すぎるため、それらの一部を別の名前空間にリファクタリングしたいが、広く使用されているプラグインAPIが分岐し、リファクタリングにより後方互換性が大幅に低下する可能性があります。このプラグインAPIは基本的に、コアコードのクラスや関数とやり取りする外部PHPファイルをロードしています。

このプロジェクトはComposerプロジェクト(理由は尋ねないでください))ではなく、自分で管理しているクラスのオートロードライブラリを使用しています。

最近、関数 class_alias 、これはこの問題に役立つ可能性があります。

メイン名前空間のクラスをサブ名前空間にリファクタリングし、プロジェクト内のクラスへの参照を更新することを検討しています。 PHPファイルに元々リファクタリングされたクラスが含まれていた(現在は移動されている)の場合)、次のように記述します。

<?php
class_alias(NewClassName::class, OldClassName::class);

これは、プラグインがOldClassNameの使用を必要とするときに、オートロードライブラリによってロードされます。私はこの方法をテストし、主要なテストはそれがうまく機能することを示しています。

次のステップは、メイン名前空間ディレクトリをクリーンアップして、リファクタリングの本当の動機を実現することです。メイン名前空間ディレクトリにはファイルが多すぎます。したがって、als(エイリアスディレクトリ)と呼ばれるソースディレクトリの横に新しいディレクトリを作成し、alsをエイリアスクラスファイルが配置されているセカンダリソースフォルダにします。

以前は、プロジェクトは次のように見えました。

src/
    src/Foo/Bar.php

これで、プロジェクトは次のようになります。

src/
    src/Foo/Bar/Bar.php

als/
    als/Foo/Bar.php

テストは、この方法が今のところうまく機能していることを示しています。

ただし、技術的/パフォーマンスの観点、ドキュメントの観点、またはコード構造の観点から考えられる副作用はありますか?私たちはこのようなことをやろうとしたことがなく、これをしている人を見たこともありません。多くの開発者がAPIの参照についてリポジトリを監視しているため、これらの変更を試す前に、より注意を払いたいと思います。

4
SOFe

オートローディングに関して考慮すべきいくつかの落とし穴がありますが、私はそれを実行し、それは可能です。私はブログ投稿でそのアプローチを説明しました:

PHP:class_aliasを使用して、クラスの移動/名前変更中にBCを維持する

概要:

  • class_alias()コードを元のクラスファイルに挿入しないでください

    問題は、タイプのヒントがオートローダーをトリガーしないことです。 _::class_定数と同様に、型ヒントは、実際に型ヒントクラスを探すことなく、渡されたオブジェクトのクラス名と比較されるクラス名に解決されます。そのため、実際のクラスがロードされたらすぐにエイリアスを配置することが重要です。

    そうでない場合、NewClassインスタンスを次の関数に渡すと、_"NewClass" != "OldClass"_およびエイリアスがまだ定義されていないため、失敗します。

    _function oldFunction(OldClass $old)
    _
  • composerまたは単一のbootstrap常にロードされるファイルを使用しない場合、私が見つけた最良の方法はclass_alias()を新しいクラスファイル:

    _\class_alias(NewClass::class, OldClass::class)
    _

    次に、誰かが実際に古いクラスをインスタンス化しようとした場合(または静的プロパティ、メソッド、または定数を使用した場合)、エイリアスを持つ新しいクラスもロードされることを確認する必要があります。これを行うには、古いクラスファイルでオートローダーをトリガーします。

    _\class_exists(NewClass::class);
    _
3