18

Doctrine2の使用を開始したばかりで、カスタムコレクションクラスをどのように/使用できるか疑問に思っています。検索は私にドキュメントのこの部分を指し示します:

Doctrine\Common\Collections\Collectionコレクション値の永続フィールドとプロパティは、インターフェイスの観点から定義する必要があります。コレクション実装タイプは、エンティティが永続化される前にフィールドまたはプロパティを初期化するためにアプリケーションによって使用される場合があります。エンティティが管理される(または切り離される)と、それ以降のアクセスはインターフェイスタイプを介して行われる必要があります。

それは誰かには非常に明確だと確信していますが、私は少し曖昧です。

コレクション変数を正しいインターフェイスを実装するクラスに初期化するようにエンティティを設定した場合(たとえば__construct())、Doctrine2はそのクラスをコレクションとして引き続き使用しますか?私はそれを正しく理解していますか?

更新:また、遅延読み込みで使用されるプレースホルダーオブジェクトが、カスタムコレクションの使用方法に影響を与える可能性があることをさまざまなスレッドから収集します。

4

3 に答える 3

23

何が可能で、何が不可能で、計画されているのかを例を挙げて明確にしようと思います。

マニュアルからの引用は、基本的に、次のカスタム実装タイプを持つことができることを意味します。

use Doctrine\Common\Collections\Collection;

// MyCollection is the "implementation type"
class MyCollection implements Collection {
    // ... interface implementation

    // This is not on the Collection interface
    public function myCustomMethod() { ... }
}

これで、次のように使用できます。

class MyEntity {
    private $items;
    public function __construct() {
        $this->items = new MyCollection;
    }
    // ... accessors/mutators ...
}

$e = new MyEntity;
$e->getItems()->add(new Item);
$e->getItems()->add(new Item);
$e->getItems()->myCustomMethod(); // calling method on implementation type

// $em instanceof EntityManager
$em->persist($e);

// from now on $e->getItems() may only be used through the interface type

つまり、エンティティがNEW(MANAGED、DETACHED、またはREMOVEDではない)である限り、具体的な実装タイプのコレクションを自由に使用できます。NEWでない場合は、インターフェイスタイプのみにアクセスする必要があります(理想的には、タイプヒントにアクセスする必要があります)。つまり、実装タイプは実際には重要ではありません。永続的なMyEntityインスタンスがデータベースから取得されるとき、MyCollectionは使用されません(Doctrineは既存の/永続的なオブジェクトのみを再構成するため、コンストラクターはDoctrineによって呼び出されません。「新しい」オブジェクトを作成することはありません)。そして、そのようなエンティティは管理されているので、アクセスはとにかくインターフェースタイプを介して行われる必要があります。

今、計画されていることに。カスタムコレクションを作成するためのより美しい方法は、実装タイプとしてIMyCollectionやMyCollectionなどのカスタムインターフェイスタイプも使用することです。次に、Doctrine 2永続化サービスで完全に機能させるには、次のようなカスタムPersistentCollection実装(たとえば、MyPersistentCollection)を実装する必要があります。

class MyPersistentCollection implements IMyCollection {
    // ...
}

次に、マッピングでDoctrineにそのコレクションにMyPersistentCollectionラッパーを使用するように指示します(PersistentCollectionはコレクション実装タイプをラップし、同じインターフェイスを実装するため、基になるコレクション実装に委任する前/後にすべての永続化作業を実行できますタイプ)。

したがって、カスタムコレクションの実装は次の3つの部分で構成されます。

  1. インターフェイスタイプ
  2. 実装タイプ(インターフェースタイプを実装)
  3. 永続ラッパータイプ(インターフェイスタイプを実装)

これにより、Doctrine 2 ORMで機能しないように見えるカスタムコレクションを作成できるだけでなく、特定のアプリケーションのニーズに合わせて特定のコレクションの遅延読み込み/初期化動作を最適化するなど、カスタムの永続ラッパータイプのみを作成することもできます。

これを行うことはまだ可能ではありませんが、可能になります。これは、Doctrine 2が提供する透過的な永続化スキームに完璧に統合された、完全にカスタムのコレクションを作成して使用するための、本当にエレガントで完全に機能する唯一の方法です。

于 2010-09-12T08:44:53.503 に答える
1

いいえ、DoctrineがDoctrine \ Common \ Collections \ Collectionインターフェースの実装を返すときはいつでも、それはDoctrine \ ORM\PersistentCollectionインスタンスになります。コレクションにこれ以上カスタムロジックを配置することはできません。しかし、それも必要ではありません。

エンティティがあり(Orderには多くのOrderItemがあります)、注文の合計を計算するメソッドは、コレクションではなく、Orderアイテムに配置する必要があります。これは、ドメインモデルで合計が意味を持つ場所であるためです。

class Order
{
    private $items;

    public function getTotalSum()
    {
        $total = 0;
        foreach ($this->items AS $item) {
            $total += $item->getSum();
        }
        return $total;
    }
}

ただし、コレクションはORMの技術的な部分にすぎず、オブジェクト間の参照の実装と管理に役立ちます。それ以上のことはありません。

于 2010-09-11T19:50:43.937 に答える
0

ここで同じ質問があります。この「機能」の詳細とステータスが記載された公式の教義Jiraの問題ページを参照してください...そこで開発を追跡できます!

于 2013-09-06T15:06:14.607 に答える