自定义收藏在Doctrine2 [英] Custom Collection in Doctrine2

查看:116
本文介绍了自定义收藏在Doctrine2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

刚刚开始使用Doctrine2,我想知道如何/如果我可以使用自定义集合类。搜索指向我文档的这一部分


集合值持久字段和属性必须以 Doctrine\Common \Collections\Collection 接口。应用程序可以使用集合实现类型在实体持久化之前初始化字段或属性。一旦实体被管理(或分离),后续的访问必须通过接口类型。


对某人,我有点模糊。



如果我设置我的Entity初始化(例如 __ construct()),正确的接口 - Doctrine2会继续使用该类作为集合吗?我正确地理解了这一点吗?



更新:此外,我从各种线程收集,延迟加载中使用的占位符对象可能会影响自定义集合可以使用。

解决方案

让我尝试澄清什么是可能的,不可能的和计划的例子。



手册中的引用基本上意味着你可以有以下自定义实现类型:

 使用Doctrine Common \Collections \Collection; 

// MyCollection是实现类型
类MyCollection实现集合{
// ...接口实现

//这不是在集合接口
public function myCustomMethod(){...}
}

现在你可以使用它如下:

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

$ e = new MyEntity;
$ e-> getItems() - > add(new Item);
$ e-> getItems() - > add(new Item);
$ e-> getItems() - > myCustomMethod(); //对实现类型调用方法

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

//从现在起$ e-> getItems()只能通过接口类型使用

换句话说,只要实体是NEW(不是MANAGED,DETACHED或REMOVED),你就可以使用集合的具体实现类型,即使它不漂亮。如果它不是新的,你必须只访问接口类型(和理想的类型提示上)。这意味着实现类型并不重要。当从数据库中检索到持久的MyEntity实例时,它不会使用MyCollection(构造函数不会被Doctrine调用,因为Doctrine只重构已经存在的/持久的对象,它从不创建新的对象)。因为这样的实体是MANAGED,所以访问必须通过接口类型进行。



现在计划什么。拥有自定义集合的更美丽的方法是还有一个自定义接口类型,说IMyCollection和MyCollection作为实现类型。然后,为了使其与Doctrine 2持久性服务完美配合,您需要实现一个自定义的PersistentCollection实现,例如MyPersistentCollection,如下所示:

 code> class MyPersistentCollection implements IMyCollection {
// ...
}

然后您将在映射中告诉Doctrine为该集合使用MyPersistentCollection包装器(记住,PersistentCollection 包装集合实现类型,实现相同的接口,以便它可以执行所有持久性因此,自定义集合实现将由3个部分组成:






$ b b


  1. 接口类型

  2. 实现类型(实现接口类型)

  3. 持久包装类型

这不仅可以编写与Doctrine 2 ORM无关的自定义集合,包装器类型,例如用于优化特定集合对特定应用程序需求的延迟加载/初始化行为。



还不可能这样做, 。这是唯一真正优雅和完全功能的方式来编写和使用完全自定义的集合,完美地集成在Doctrine 2提供的透明持久化方案。


Just starting to work with Doctrine2, and am wondering how/if I can use a custom collection class. Searches point me to this part of the documentation:

Collection-valued persistent fields and properties must be defined in terms of the Doctrine\Common\Collections\Collection interface. The collection implementation type may be used by the application to initialize fields or properties before the entity is made persistent. Once the entity becomes managed (or detached), subsequent access must be through the interface type.

While I'm sure that's crystal clear to someone, I'm a little fuzzy on it.

If I setup my Entity to initialize (say in __construct()) the collection variable to a class that implements the correct interface - will Doctrine2 continue to use that class as the collection? Am I understanding that correctly?

Update: Also, I gather from various threads that the placeholder object used in lazy loading may influence how a custom collection can be used.

解决方案

Let me try to clarify what is possible, not possible and planned with examples.

The quote from the manual basically means you could have the following custom implementation type:

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() { ... }
}

Now you could use it as follows:

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

In other words, as long as an entity is NEW (not MANAGED, DETACHED or REMOVED) you are free to use the concrete implementation type of collections, even if its not pretty. If it is not NEW, you must access only the interface type (and ideally type-hint on it). That means the implementation type does not really matter. When a persistent MyEntity instance is retrieved from the database, it will not use a MyCollection (constructors are not invoked by Doctrine, ever, since Doctrine only reconstitutes already existing/persistent objects, it never creates "new" ones). And since such an entity is MANAGED, access must happen through the interface type anyways.

Now to what is planned. The more beautiful way to have custom collections is to also have a custom interface type, say IMyCollection and MyCollection as the implementation type. Then, to make it work perfectly with the Doctrine 2 persistence services you would need to implement a custom PersistentCollection implementation, say, MyPersistentCollection which looks like this:

class MyPersistentCollection implements IMyCollection {
    // ...
}

Then you would tell Doctrine in the mapping to use the MyPersistentCollection wrapper for that collection (remember, a PersistentCollection wraps a collection implementation type, implementing the same interface, so that it can do all the persistence work before/after delegating to the underlying collection implementation type).

So a custom collection implementation would consist of 3 parts:

  1. Interface type
  2. Implementation type (implements interface type)
  3. Persistent wrapper type (implements interface type)

This will not only make it possible to write custom collections that work seemlessly with the Doctrine 2 ORM but also to write only a custom persistent wrapper type, for example to optimise the lazy-loading/initialization behavior of a particular collection to specific application needs.

It is not yet possible to do this but it will be. This is the only really elegant and fully functional way to write and use completely custom collections that integrate flawlessly in the transparent persistence scheme provided by Doctrine 2.

这篇关于自定义收藏在Doctrine2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆