我有几个不同的doctrine实体实现了一个通用接口,我想(理想情况下)在doctrine中创建一个存储库,允许我在所有这些实体(简单SQL中的联合)中使用排序/分页进行查询。实体不会从公共基类继承。
具体来说,界面允许将对象用作标记:
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 :(得分: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
答案 1 :(得分: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)。 p>