多对多自我引用Query_builder

时间:2016-09-23 13:18:04

标签: symfony doctrine-orm

我有一个名为Status的实体,它具有自引用多对多关系,以定义下一个可用状态的每个状态:

class Status
{
    private $id;

    //...

    /**
     * @ORM\ManyToMany(targetEntity="Status", mappedBy="nextStatuses")
     */
    private $previousStatuses;

    /**
     * @ORM\ManyToMany(targetEntity="Status", inversedBy="previousStatuses")
     * @ORM\JoinTable(name="status_mapping",
     *      joinColumns={@ORM\JoinColumn(name="status_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="next_status_id", referencedColumnName="id")}
     *      )
     */
    private $nextStatuses;

    /**
     * @ORM\OneToMany(targetEntity="OrderStatus", mappedBy="status")
     * @ORM\OrderBy({"createdTime" = "ASC"})
     */
    private $orderStatuses;

    //...    

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->nextStatuses = new \Doctrine\Common\Collections\ArrayCollection();
        $this->previousStatuses = new \Doctrine\Common\Collections\ArrayCollection();
    }

    //...
}

我正在创建表单类型,需要将状态实体添加为字段并将其选择限制为$nextStatuses问题是EntityType需要query_builder而我不能简单地说$status->getNextStatuses()

我目前拥有的(并且有一些变体,但没有一个有效):

public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //Current status passed as option
        $status = $options['status'];
        $builder->add('status', EntityType::class, array(
            'class' => 'AppBundle\Entity\Status',
            'query_builder' => function (StatusRepository $er) use ($status) {
                return $er->createQueryBuilder('s')
                    ->leftJoin('s.previousStatuses', 'ps')
                    ->where('s.previousStatuses = :status')
                    ->setParameter('status', $status);
            },));

}

以上查询导致错误[Semantical Error] line 0, col 80 near 'previousStatuses': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.

1 个答案:

答案 0 :(得分:2)

previousStatuses关联是ArrayCollection所以对于Doctrine这个陈述是错误的:

->where('s.previousStatuses = :status')

使用ps clausule中的where别名,如下所示:

//...
return $er->createQueryBuilder('s')
   ->leftJoin('s.previousStatuses', 'ps')
   ->where('ps.id = :status') // <---- here
   ->setParameter('status', $status);

我认为status实体的Status字段,但可以是name或其他任何字段,在您的实体中进行检查。