所以我是这两个实体:
class TipoRegistro
{
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\TipoTramite", inversedBy="tipoRegistros", cascade={"persist"})
* @ORM\JoinTable(name="nomencladores.tipo_registro_tipo_tramite", schema="nomencladores",
* joinColumns={@ORM\JoinColumn(name="tipo_registro_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")}
* )
*/
protected $tipoTramites;
}
class TipoTramite
{
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\TipoRegistro", mappedBy="tipoTramites", cascade={"persist"})
*/
protected $tipoRegistros;
}
我需要将所有与TipoRegistro
关联的TipoTramite
与之前显示的ManyToMany关系相关联,如下面的SQL所示:
SELECT tr.*
FROM
nomencladores.tipo_registro tr
LEFT JOIN
nomencladores.tipo_registro_tipo_tramite AS trtt
ON (trtt.tipo_registro_id = tr."id")
WHERE
tr.activo = true
AND
trtt.tipo_tramite_id = 1;
我不知道我是否可以在此处使用自定义存储库,因此我唯一的解决方案是在表单级别使用query_builder
参数,这就是我正在做的事情:
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('tr')
->where('tr.activo = :activo')
->leftJoin('tr.tipoTramites', 'ttr')
->andWhere("ttr.tipo_tramite_id = :tramite")
->setParameter("tramite", 1)
->setParameter('activo', true);
}
但该解决方案会导致此错误:
[语义错误]第0行,第121行附近' tipo_tramite_id':错误: 类AppBundle \ Entity \ TipoTramite没有字段或 名为tipo_tramite_id的协会
我也尝试了这个(按照每位用户的建议):
->andWhere("ttr.tipoTramites = :tramite")
但错误变成了这个:
[语义错误]第0行,第120行附近' tipoTramites':错误:无效 PathExpression。 StateFieldPathExpression或 SingleValuedAssociationField预期
此外,我还尝试了其他解决方案:
->andWhere("tr.id = :tramite")
但是这个没有返回正确的值。我在实体字段类型上阅读了关于Closures
的内容,但不知道如何在这种情况下实现。我想到的另一个想法是使用DQL和准备语句,但我认为这不能在表单级别使用,所以我没有想法,那么我如何获得这些值?我应该如何建立这个ManyToMany实体之间的关系?
答案 0 :(得分:2)
当您在实体中创建ManyToMany关系时,Doctrine将生成第三个表作为这两个实体(在@ORM\JoinTable
中命名)之间的中介,其中包含两个字段(在joinColumns
中定义)。您无法直接访问第三个表中的字段或列,但它们都将由DQL中的Doctrine处理。
这意味着在您的DQL中,您只需要在where子句中设置联合表id而不是真实的字段名称,Doctrine将生成正确的SQL:
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('tr')
->where('tr.activo = :activo')
->leftJoin('tr.tipoTramites', 'ttr')
->andWhere("ttr.id = :tramite")
->setParameter("tramite", 1)
->setParameter('activo', true);
}
这将生成正确的SQL 唯一的提示是您无权访问DQL中第三个表的生成字段,但它将由Doctrine处理,您可以使用连接表ID