实现公共接口的实体的Doctrine存储库

时间:2017-02-06 14:47:46

标签: php doctrine-orm orm

我有几个不同的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来实现这一目标?

非常感谢。

2 个答案:

答案 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>