Собственная коллекция в Doctrine2 - PullRequest
14 голосов
/ 11 сентября 2010

Я только начинаю работать с Doctrine2, и мне интересно, как / если я могу использовать пользовательский класс коллекции.Поиски указывают на эту часть документации :

Постоянные поля и свойства с коллекционными значениями должны быть определены в терминах интерфейса Doctrine\Common\Collections\Collection.Тип реализации коллекции может использоваться приложением для инициализации полей или свойств до того, как объект станет постоянным.Как только сущность становится управляемой (или отсоединенной), последующий доступ должен осуществляться через тип интерфейса.

Хотя я уверен, что это кому-то совершенно ясно, я немного не уверен в этом.

Если я настрою свою сущность для инициализации (скажем, в __construct()) переменной коллекции для класса, который реализует правильный интерфейс - будет ли Doctrine2 продолжать использовать этот класс в качестве коллекции?Правильно ли я понимаю?

Обновление : Кроме того, я собираю из различных потоков, что объект-заполнитель, используемый при отложенной загрузке, может влиять на то, как можно использовать собственную коллекцию.

Ответы [ 3 ]

20 голосов
/ 12 сентября 2010

Позвольте мне попытаться уточнить, что возможно, что невозможно и что планируется с примерами.

Цитата из руководства в основном означает, что вы можете иметь следующий пользовательский тип реализации:

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

Другими словами, до тех пор, пока сущность является НОВОЙ (не УПРАВЛЯЕМОЙ, НЕ ОБНАРУЖЕННОЙ или УДАЛЕННОЙ), вы можете использовать конкретный тип реализации коллекций, даже еслиэто не красиво.Если он не НОВЫЙ, вы должны получить доступ только к типу интерфейса (и в идеале к нему подсказка типа).Это означает, что тип реализации не имеет большого значения.Когда постоянный экземпляр MyEntity извлекается из базы данных, он не будет использовать MyCollection (конструкторы никогда не вызываются Doctrine, поскольку Doctrine только воссоздает уже существующие / постоянные объекты, но никогда не создает «новые»).И поскольку такая сущность УПРАВЛЯЕТСЯ, доступ в любом случае должен осуществляться через тип интерфейса.

Теперь к тому, что планируется.Более красивый способ иметь пользовательские коллекции - это также иметь пользовательский тип интерфейса, например, IMyCollection и MyCollection в качестве типа реализации.Затем, чтобы он идеально работал со службами персистентности Doctrine 2, вам необходимо реализовать собственную реализацию PersistentCollection, скажем, MyPersistentCollection, которая выглядит следующим образом:

class MyPersistentCollection implements IMyCollection {
    // ...
}

Затем вы указываете Doctrine в отображении использоватьоболочка MyPersistentCollection для этой коллекции (не забывайте, что PersistentCollection включает тип реализации коллекции, реализующий тот же интерфейс, так что он может выполнять всю работу по сохранению до / после делегирования базовому типу реализации коллекции).

Таким образом, реализация пользовательской коллекции будет состоять из 3 частей:

  1. Тип интерфейса
  2. Тип реализации (реализует тип интерфейса)
  3. Постоянный тип оболочки (реализует тип интерфейса)

Это позволит не только создавать пользовательские коллекции, которые, как кажется, работают с ORM в Doctrine 2, но и писать только пользовательский тип персистентной оболочки, например, для оптимизации.Настройте ленивую загрузку / инициализацию определенного набора для конкретных нужд приложения.

Пока это невозможно сделать, но это будет так.Это единственный действительно элегантный и полностью функциональный способ написания и использования полностью пользовательских коллекций, которые безупречно интегрируются в прозрачную схему персистентности, представленную в Doctrine 2.

0 голосов
/ 06 сентября 2013

Тот же вопрос здесь , со ссылкой на официальную страницу выпуска Jira со сведениями и статусом этой «функции» ... Вы можете следить за развитием там !

0 голосов
/ 11 сентября 2010

Нет, всякий раз, когда Doctrine возвращает вам реализацию интерфейса Doctrine \ Common \ Collections \ Collection, это будет экземпляр Doctrine \ ORM \ PersistentCollection. Вы не можете поместить больше пользовательской логики в коллекцию. Однако это даже не обязательно.

Скажем, у вас есть сущность (у Order есть много OrderItems), тогда метод для расчета общей суммы заказа должен располагаться не в коллекции, а в позиции Order. Так как это место, где сумма имеет значение в модели вашего домена:

class Order
{
    private $items;

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

Коллекции, однако, являются только техническими частями ORM, они помогают реализовывать ссылки между объектами и управлять ими, не более того.

...