7

Product現在、Zend Framework 2 と Doctrine 2 を使用して、非常に柔軟でモジュール化されたアプリケーションを開発しています。このアプリケーションには、複数の Doctrine エンティティがあります。たとえば、モジュール内のエンティティとしましょうProducts。このモジュールProductsは、製品管理のベース/デフォルト モジュールです。

Products顧客 ( ) 用のカスタム モジュールを作成できるようにしたいと考えていますXProducts。したがって、拡張する新しいエンティティXProduct(いくつかの追加フィールドを含む) を作成しましたProduct

したがって、カスタム モジュールが有効になっている場合は、XProductand elseを使用したいのですProductが、(同じプロジェクト内で) 一緒に使用することはありません。

@Entity で両方のエンティティに注釈を付けると、部分的に機能します。たとえばfindAll、完全にfind機能しますが、機能しません。作成された SELECT ステートメントには正しい列が含まれていますが、WHERE 句が間違っています。例えば:

SELECT t1.id AS id2, t1.name AS name3 FROM products t1 WHERE t0.id = ?

は forとfor をt1表していると思いますが、列が正しい ( ) のに where 句が正しくない ( ) 理由がわかりません。ProductXt0Productt1t0

Doctrine が継承を実現するために単一テーブル継承を提供していることは承知していますが、したがって、DiscriminatorColumn が必要であり、ベース/デフォルト エンティティで DiscriminatorMap を定義する必要があります。顧客用の新しいカスタム モジュールを追加する場合、ベース/デフォルト モジュールを変更する必要があるため、これは私たちには適していません (それは私たちが望んでいるものではありません...)。

誰もこの問題を解決する手がかりを持っていますか? ありがとう!

4

2 に答える 2

7

最後にこの問題を修正しました。すべてのデフォルト/ベース クラスに対して、追加の抽象 MappedSuperclass を作成しました (Jurian Sluiman が述べたように)。たとえばProduct、顧客の特定のエンティティには、次のものが必要です。

  • AbstractProduct (すべてのデフォルト/基本機能を含む)
  • Product (空で、AbstractProduct を拡張するデフォルト/基本クラス)
  • XProduct (お客様向けの追加機能を含み、AbstractProduct を拡張します)

MappedSuperclass の関連付けに関する問題を解決するために、抽象クラスを参照します。次に例を示します。 @ORM\OneToOne(targetEntity="ProductManagement\Entity\AbstractProduct")

次に、Doctrine の EntityResolver ( http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/resolve-target-entity-listener.htmlを参照) を使用して、抽象クラス (またはインターフェイス) をマップします。実体への関連付け (設定による):

'entity_resolver' => array(
    'orm_default' => array(
        'resolvers' => array(
            // Note: Use only one
            'ProductManagement\Entity\AbstractProduct' => 'ProductManagement\Entity\Product', // Default
            'ProductManagement\Entity\AbstractProduct' => 'XProductManagement\Entity\XProduct', // For customer X
        )
    )
)

このようにして、デフォルト/ベースモジュールとエンティティを変更せずに、エンティティを顧客の特定のエンティティでオーバーライドできます (これはまさに私が探していたものです)。

于 2013-07-18T09:49:05.393 に答える
3

私たちはこのパターンを使用し、Doctrine を使用するのが最も簡単です (ただし、多くの醜いコードを使用すると、OOP をより賢くすることができます)。インスタンスが複数のインスタンスを使用できるPortfolioモジュールの例を見てみましょう。PortfolioItem

マッピングされたスーパークラスから拡張されたPortfolioエンティティを操作しますAbstractPortfolio。特別なフィールドを必要とするクライアントがいる場合はClientPortfolio、マップされたスーパークラスを拡張して作成し、すべてのプロパティを正しくオーバーロードします。

クラス名は構成で指定され、その文字列はリポジトリのファクトリなどで使用されます。リポジトリをロードすることはありませんが、デフォルト ポートフォリオの名前でサービス マネージャからリポジトリ クラスを要求する場合でもPortfolio常にロードします。ClientPortfolio

このメソッドは、ここのようなリポジトリ関数で問題なく機能します(ただし、このクラスは のリポジトリであり、 ではItemありませんPortfolio)。相互に複数のエンティティを使用しないため、単一テーブルの継承は使用しません。少なくとも、それは私たちの場合です。

于 2013-07-11T20:20:56.867 に答える