所以我有两个实体:
class TipoRegistro
{
/**
* @ORMManyToMany(targetEntity="AppBundleEntityTipoTramite", inversedBy="tipoRegistros", cascade={"persist"})
* @ORMJoinTable(name="nomencladores.tipo_registro_tipo_tramite", schema="nomencladores",
* joinColumns={@ORMJoinColumn(name="tipo_registro_id", referencedColumnName="id")},
* inverseJoinColumns={@ORMJoinColumn(name="tipo_tramite_id", referencedColumnName="id")}
* )
*/
protected $tipoTramites;
}
class TipoTramite
{
/**
* @ORMManyToMany(targetEntity="AppBundleEntityTipoRegistro", mappedBy="tipoTramites", cascade={"persist"})
*/
protected $tipoRegistros;
}
我需要获取与 trhough ManyToMany 关系相关的所有TipoRegistro
TipoTramite
如前所示,如下面的 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":错误:无效 路径表达式。StateFieldPathExpression 或 单值关联预期字段
我也尝试了其他解决方案:
->andWhere("tr.id = :tramite")
但是这个不会返回正确的值。我阅读了一些有关实体字段类型的Closures
,但不知道如何在这种情况下实现。我想到的另一个想法是使用 DQL 和准备语句,但我瘦了,这不能在表单级别使用,所以我没有想法,那么我如何获得这些值?我应该如何建立这个多对多实体之间的关系?
当您在实体中创建 ManyToMany 关系时,Doctrine 将生成第三个表作为这两个实体(在 @ORMJoinTable
中命名)之间的中介,其中包含两个字段(在 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代替