web-dev-qa-db-ja.com

PHPでのファクトリパターンと動的クラスのインスタンス化

PHPでWebフレームワークを開発していますが、完全に拡張可能にしたいと考えています。私の目標は、開発者が「コア」コードベースをまったく変更しなくても、コンポーネントの動作を変更できるようにすることです。開発者は、すべての作業を別のディレクトリにカプセル化できる必要があります。そして、すぐに巨大な混乱になりかねない「フック」(つまり、イベントリスナー)を使用せずにこれを実行したいと思います。

ほとんどのコンポーネントについて、私はこれを理解しました:

  • Pimple DIコンテナを使用すると、既存のサービスをextendできます。
  • 私は Twig をテンプレートエンジンとして使用しています。これにより、テンプレートをオーバーライドできます。
  • フロントコントローラーのルートは、再定義することでオーバーライドできます。
  • 私は拡張可能な ユニフォームリソースロケーター を使用して、開発者がリソース(アセット、構成、スキーマなど)の検索パスを上書きまたは追加できるようにしています。

私が直面している問題は、コアのコードベースにそのクラスを既にインスタンス化している場所がある場合にクラスの機能を拡張することです(私のフレームワークはライブラリではなく本格的なアプリケーションであるため、IoCを使用しても、クラスをインスタンス化する必要があります) ある時点)で。

コアコントローラー/ルート/何でも基本クラスをインスタンス化しているため、継承だけではこの問題は解決しません。抽象化の追加レイヤーを導入する必要があるようです。

私の考えの1つは、PHPの動的クラスのインスタンス化機能を使用することです。たとえば、ベースのUserクラスがあり、開発者がすべてのインスタンスをCustomUserクラスに置き換えられるようにしたい場合:

// In a config file (which *can* be overridden) 
$userClassName = "User";

...

// Anywhere I need a User, or User subclass: 
$user = new $userClassName(...);

これで、開発者は$userClassNameの値をオーバーライドして、子クラスの名前に設定するだけです。

または、これをすべてFactoryパターンでラップすることもできます。

class UserFactory
{
    public function createUser($type = "User", $args)
    {
        return new $type($args);
    }
}

Factoryクラスの利点は、型チェックを実行できることですが、その場合、基本クラスごとに個別のFactoryが必要になります。

これらのアプローチのいずれかが、この種の拡張性を実装する正しい方法ですか?

4
alexw

私の目標は、開発者が「コア」を変更せずにコンポーネントの動作を変更できるようにすることです

ここでは、基本クラスの実装でインターフェイスを使用したいと思います。開発者はこのクラスを使用するか、インターフェイスを実装する新しいクラスを導入できます。

動的クラス名は検出できず、技術的な負担が増える可能性があります。

あなたのコントローラー/ルート/何でもPimple Dependency Containerを持つでしょう。開発者はカスタムクラスオブジェクトを挿入し、コアはこの挿入されたカスタムクラスのオブジェクトを作成します。

1