如何从存储库中获取鉴别器类型
How to get the discriminator type from repository
我目前正在为我的学说实体之一使用单个 table 继承。 header 看起来像这样:
/**
* Flux
*
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({"flux" = "Flux", "news" = "FluxNews", "mission" = "FluxMission", "offer" = "FluxOffer", "survey" = "FluxSurvey", "linkedin" = "FluxLinkedin", "facebook" = "FluxFacebook", "youtube" = "FluxYoutube", "twitter" = "FluxTwitter"})
* @ORM\Entity(repositoryClass="AppBundle\Repository\FluxRepository")
*/
class Flux
{
protected $type = "flux";
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/* other fields */
}
我正在尝试在通量存储库中创建一个函数,该函数将从所有通量 object 中获取数据。我要收集的重要数据之一是 object(鉴别器字段)的类型,以了解它是哪种 object。
在我的存储库中,我的 select 看起来像这样:
$queryBuilder->select('f.id', 'f.type', 'f.createdAt', 'IDENTITY(f.createdBy) as CreatedBy','COUNT(DISTINCT c.id) as allClicks', 'COUNT(DISTINCT IDENTITY(c.clicker)) as clicks', 'f.postUrl')
->groupBy('f.id');
f
是 flux
。如果我删除 'f.type'
它可以正常工作,但我需要该数据。
如果我保留 'f.type'
,我会收到以下错误:
[Semantical Error] line 0, col 15 near 'type, f.createdAt,': Error: Class AppBundle\Entity\Flux\Flux has no field or association named type
我猜是因为type是discriminator字段,所以不在normal字段中。有没有办法让我访问存储库中的数据?
我可以在我的控制器中访问,但我真的很想保持我的代码干净,并在存储库中对这些数据进行所有查询。
到目前为止我看到的唯一选择是创建另一个仅保存相同类型的字段但它确实不干净,我想知道是否有一种方法可以使用学说来获取该字段的值。
请参阅this question。不过我觉得这样真的是over-complicated.
如果我是你,我会直接覆盖你的查询。像这样:
$queryBuilder->select(f, COUNT(DISTINCT c.id) as allClicks, COUNT(DISTINCT IDENTITY(c.clicker)) as clicks)->from(Flux f)->groupBy(f.id);
您会得到不同的结果,请参阅 docs
因此,从 f
获取您需要的类型。
希望你明白了。
根据 docs,您可以使用 INSTANCE OF 来完成。
因为你想使用鉴别器值,使用 class 元数据 并构造一个 CASE 表达式,你可以select 每个实例的值:
$meta = $em->getMetadataFactory()->getMetadataFor(Flux::class);
$discriminatorMap = $meta->discriminatorMap;
$caseQl = '(case';
foreach ($discriminatorMap as $fieldValue => $class) {
$caseQl .= " when p INSTANCE OF " . $class . " then '" . $fieldValue . "'";
}
$caseQl .= ' else 0 end) as HIDDEN atype';
$qb->addSelect($caseQl);
$qb->having("atype LIKE :type");
$qb->setParameter('type', '%FluxNew%');
注意字段atype被定义为HIDDEN,所以它不会在结果中返回。
对于此解决方案,还需要使用 having,而不是 where(因为 atype 是计算值)。
或者,您可以使用 Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS 在结果中包含外键列值:
$paginator->getQuery()
->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);
参考文献:
- how to get discriminator map values
- Calculated column
我目前正在为我的学说实体之一使用单个 table 继承。 header 看起来像这样:
/**
* Flux
*
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({"flux" = "Flux", "news" = "FluxNews", "mission" = "FluxMission", "offer" = "FluxOffer", "survey" = "FluxSurvey", "linkedin" = "FluxLinkedin", "facebook" = "FluxFacebook", "youtube" = "FluxYoutube", "twitter" = "FluxTwitter"})
* @ORM\Entity(repositoryClass="AppBundle\Repository\FluxRepository")
*/
class Flux
{
protected $type = "flux";
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/* other fields */
}
我正在尝试在通量存储库中创建一个函数,该函数将从所有通量 object 中获取数据。我要收集的重要数据之一是 object(鉴别器字段)的类型,以了解它是哪种 object。
在我的存储库中,我的 select 看起来像这样:
$queryBuilder->select('f.id', 'f.type', 'f.createdAt', 'IDENTITY(f.createdBy) as CreatedBy','COUNT(DISTINCT c.id) as allClicks', 'COUNT(DISTINCT IDENTITY(c.clicker)) as clicks', 'f.postUrl')
->groupBy('f.id');
f
是 flux
。如果我删除 'f.type'
它可以正常工作,但我需要该数据。
如果我保留 'f.type'
,我会收到以下错误:
[Semantical Error] line 0, col 15 near 'type, f.createdAt,': Error: Class AppBundle\Entity\Flux\Flux has no field or association named type
我猜是因为type是discriminator字段,所以不在normal字段中。有没有办法让我访问存储库中的数据?
我可以在我的控制器中访问,但我真的很想保持我的代码干净,并在存储库中对这些数据进行所有查询。 到目前为止我看到的唯一选择是创建另一个仅保存相同类型的字段但它确实不干净,我想知道是否有一种方法可以使用学说来获取该字段的值。
请参阅this question。不过我觉得这样真的是over-complicated.
如果我是你,我会直接覆盖你的查询。像这样:
$queryBuilder->select(f, COUNT(DISTINCT c.id) as allClicks, COUNT(DISTINCT IDENTITY(c.clicker)) as clicks)->from(Flux f)->groupBy(f.id);
您会得到不同的结果,请参阅 docs
因此,从 f
获取您需要的类型。
希望你明白了。
根据 docs,您可以使用 INSTANCE OF 来完成。
因为你想使用鉴别器值,使用 class 元数据 并构造一个 CASE 表达式,你可以select 每个实例的值:
$meta = $em->getMetadataFactory()->getMetadataFor(Flux::class);
$discriminatorMap = $meta->discriminatorMap;
$caseQl = '(case';
foreach ($discriminatorMap as $fieldValue => $class) {
$caseQl .= " when p INSTANCE OF " . $class . " then '" . $fieldValue . "'";
}
$caseQl .= ' else 0 end) as HIDDEN atype';
$qb->addSelect($caseQl);
$qb->having("atype LIKE :type");
$qb->setParameter('type', '%FluxNew%');
注意字段atype被定义为HIDDEN,所以它不会在结果中返回。
对于此解决方案,还需要使用 having,而不是 where(因为 atype 是计算值)。
或者,您可以使用 Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS 在结果中包含外键列值:
$paginator->getQuery()
->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);
参考文献:
- how to get discriminator map values
- Calculated column