使用两个实体之间的额外属性编辑关系n:m的表单

时间:2014-09-17 03:29:58

标签: php symfony symfony-forms symfony-2.5

我在两个实体之间有这种映射:

class Orders {
    // Other attributes 

    /**
     * @ORM\OneToMany(targetEntity="OrderHasProduct", mappedBy="order") 
     */
    protected $orderProducts;

    // Other set/get methods

    public function getOrderProducts()
    {
        return $this->orderProducts;
    }
}

class Product {
    // Other attributes

    /**
     * @ORM\OneToMany(targetEntity="\Tanane\FrontendBundle\Entity\OrderHasProduct", mappedBy="product")
     */
    protected $orderProducts;

    // Other set/get methods

    public function getOrderProducts()
    {
        return $this->orderProducts;
    }
}

当然,由于许多订单可以有很多产品,但还有一个额外的属性需要这个其他实体:

class OrderHasProduct
{
    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="\Tanane\FrontendBundle\Entity\Orders")
     * @ORM\JoinColumn(name="general_orders_id", referencedColumnName="id")
     */
    protected $order;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="\Tanane\ProductBundle\Entity\Product")
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
     */
    protected $product;

    /**
     * @ORM\Column(type="integer", nullable=false)
     */
    protected $amount;

    public function setOrder(\Tanane\FrontendBundle\Entity\Orders $order)
    {
        $this->order = $order;
    }

    public function getOrder()
    {
        return $this->order;
    }

    public function setProduct(\Tanane\ProductBundle\Entity\Product $product)
    {
        $this->product = $product;
    }

    public function getProduct()
    {
        return $this->product;
    }

    public function setAmount($amount)
    {
        $this->amount = $amount;
    }

    public function getAmount()
    {
        return $this->amount;
    }
}

当我编辑订单时,我应该能够添加/删除该订单上的产品,但我不知道如何实现这一目标。我知道我必须使用form collection但是如何?我的意思是应该嵌入一个集合如下:

$builder->add('product', 'collection', array(
    'type' => new OrderHasProductType(),
    'allow_add' => true,
    'allow_delete' => true
));

当我应该创建一个新的OrderHasProductType表单时,我想我明白了,但现在我的问题是,订单的ID会发生什么变化?什么是处理嵌入形式的关系n:m与额外参数的正确方法?

可以给我一些代码示例来订购我的想法吗?

额外资源

1 个答案:

答案 0 :(得分:1)

我认为你的情况有点复杂,因为没有与两个实体的标准Doctrine多对多关系,而是两个独立的一对多和多对一关系,有三个实体。

通常,对于完整的多对多,该过程将具有例如OrderType表单,其包含充满ProductTypes的Collection字段,该ProductTypes表示分配给Order的Products。

'allow_add' => true表示如果Symfony看到一个没有ID的条目,它希望它是一个通过Javascript添加的全新项目,并且很乐意调用表单Valid并将新项目添加到实体。'allow_delete' => true反过来意味着如果缺少其中一个项目,那么Symfony会将其从实体中删除。)

但是,您还有一个级别的实体,它会Order->OrderHasProduct->Product。因此,逻辑上您的OrderType表单包含OrderHasProductType表单的集合(如上所述),而表单又包含ProductType表单。

所以你的OrderType变得更像这样:

$builder->add('orderHasProducts', 'collection', array(
    'type' => new OrderHasProductType(),
    'allow_add' => true,
    'allow_delete' => true
));

您还有另一个级别的产品:

OrderHasProductType

$builder->add('product', 'collection', array(
    'type' => new ProductType(),
    'allow_add' => true,
    'allow_delete' => true
));

还有ProductType:

$builder->add('product', 'entity', array(
    'class' => 'ProductBundle:Product'
));

Symfony应该乐意将您的实体映射到正确的类型级别。在您的视图中,您需要包含Javascript,它将理解向订单添加产品还涉及ProductHasOrder级别 - 最好放入一些数据并查看Symfony如何将其转换为表单,然后模仿Javascript中的结构。