2017-02-06 9 views
1

У меня есть несколько разных доктринных объектов, реализующих общий интерфейс, и я хочу (в идеале) создать репозиторий в доктрине, который позволяет мне запрашивать с упорядочением/разбиением на страницы по всем этим объектам (объединение в простом SQL). Объекты не наследуются от общего базового класса.Репозиторий Doctrine для объектов, реализующих общий интерфейс

В частности, интерфейс позволяет объекту использовать в качестве метки:

interface My\TaggableInterface 
{ 
    // get object UUID 
    public function getObjectIdentity(): string 
    // get the tag text 
    public function getTagString(): string 
} 

class My\Entity implements My\TaggableInterface 

class My\Other\Entity implements My\TaggableInterface 

Я надеялся создать пользовательское хранилище, управляемое объединение, так что я мог бы написать:

$entityManager()->getRepository('My\\TaggableInterface') 
    ->findBy(
     //criteria 
    )` 

Но похоже, не существует способа создать временную таблицу из интерфейса или support for union in the doctrine query builder. Я хочу избежать использования собственного (My) SQL, если это возможно, но я не вижу, как это сделать с помощью Doctrine?

Большое спасибо.

+0

Невозможно предоставить репозитории между объектами в Доктрине. Вы можете создать настраиваемый репозиторий для каждого объекта, а затем реализовать свой материал с тэгами через либо свойство, либо базовый репозиторий. – Cerad

ответ

1

Вы не можете сделать это с помощью одного запроса. Даже если бы вы могли каким-то образом построить этот запрос, доктрина не знала, как увлажнить результаты.

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

$result = array(); 
$criteria = array(
    // criteria 
); 
foreach ($em->getMetadataFactory()->getAllMetadata() as $m) { 
    $class = $m->getName(); 
    $reflClass = new \ReflectionClass($class); 
    if ($reflClass->implementsInterface('My\TaggableInterface')) { 
     $result = array_merge($result, $em->getRepository($class)->findBy($criteria)); 
    } 
} 
// results of various entity classes are now all in $result 
+0

Это нормально, но это означает загрузку всех результатов запроса для сортировки и разбиения на страницы данных. Я думаю, что мне придется использовать 'EntityManager :: createNativeQuery' и класс ResultSetMapping для того, что я хочу, но это лучшее, что можно сделать с ORM. – avy

+0

К сожалению, даже с помощью собственного SQL и ResultSetMapping AFAIK вы не можете убрать разные строки результатов из запроса UNION в разные классы сущностей. Я думаю, для того, чтобы сделать эту работу, вам также нужно написать специальный гидрант (см. Https://techpunch.co.uk/development/create-custom-doctrine2-hydrator-symfony2 для начала). – aferber

+0

В моем случае все они гидратированы для тегов сущностей. Я использовал функцию '' UUID() 'MySQL для создания идентификатора для нового тега, а затем, если пользователь сохраняет этот тег, он может обрабатываться точно так же, как и те, которые существуют в реальном теге (см. Ниже). Это немного грязно, но в этом случае это будет работать. – avy

0

Схема решения я использовал ниже. Поскольку я убираю результаты из каждой таблицы в объект тега (который может сохраняться с использованием ORM, если тег выбран пользователем), нет необходимости гидратировать несколько классов сущностей из одного и того же набора результатов.

$sql = <<<EOF 
    SELECT `id`, `text` 
    FROM tag_table 
    GROUP BY `text` 
    UNION 
    SELECT UUID() as `id`, `some_text_field` as `text` 
    FROM another_table 
    GROUP BY `some_text_field` 
EOF; 

$resultMapping = new ResultSetMapping(); 
$resultMapping->addEntityResult('My\Tag\Entity', 'tag'); 
$resultMapping->addFieldResult('tag', 'id', 'id'); 
$resultMapping->addFieldResult('tag', 'text', 'text'); 
$nativeQuery = $entityManager->createNativeQuery($sql, $resultMapping); 

$result = $nativeQuery->getResult(); 

SQL, может быть расширено для обработки пагинации, и чтобы убедиться, что используется таблица тегов объекта (вместо вновь образованного UUID для того же самого текста тега), когда дублирующие записи через таблицы удаляются союз.

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

  • Нет связанных вопросов^_^