2010-09-11 4 views
14

Просто начал работать с Doctrine2, и мне интересно, как/если я могу использовать собственный класс коллекции. Поисковые мне точку this part of the documentation:Пользовательская коллекция в Doctrine2

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

Хотя я уверен, что это ясно для кого-то, я немного расплывчатый на нем.

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

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

+1

Для тех, кто пришел сюда, пытаясь найти ответ: На данный момент [feature] (https://github.com/doctrine/doctrine2/issues/5057) по-прежнему не реализована, внесите свой вклад в обсуждение функций (upvotes, варианты использования, ваши решения). – Arkemlar

ответ

18

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

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

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

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

class MyPersistentCollection implements IMyCollection { 
    // ... 
} 

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

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

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

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

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

+0

Отличная деталь здесь и очень хорошо объяснила. Уточнила документацию для меня. – cantera

+0

Здравствуйте, теперь прошло 2 года с того времени, когда вы написали, что «это запланировано», но, как я вижу, это все еще не так. Есть ли у вас какие-либо подсказки, когда эта функция может быть реализована? – grongor

+0

+1 Интересно, надеется ли это, что это сделано. Я нахожусь в Доктрине 2.3, но не видят никаких указаний на возможность включения этого подхода. –

0

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

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

class Order 
{ 
    private $items; 

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

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

+0

Моя основная мысль заключалась в том, чтобы обеспечить порядок/сортировку/фильтрацию, а не выполнять вычисления на объектах. –

+0

Даже методы сортировки/фильтрации лучше всего наносить на объекты, которые хранят коллекцию. Однако существуют также методы, которые принимают закрытие и выполняют работу для вас, например: $ collection-> map (function ($ element) {return $ element-> getProperty();}); – beberlei

+0

@beberlei Но если несколько объектов имеют одну и ту же коллекцию, вы получаете дублирующий код (если вы не используете анонимные функции). –

0

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

Смежные вопросы