基于数组 collection 中的实体创建表单

Create form based on Entity from array collection

尝试使用 symfony and doctrine 创建一个简单的网上商店。问题是:我不知道如何创建应该能够 select/set 每个产品数量的订单。我想我需要 3 个实体 Product、Order 和 OrderPosition。

产品有价格和标题。 Order 知道哪个用户在什么时候下了订单,但在这种情况下相关的是 Order 有 OrderPositions 并且 OrderPositions 有 属性 数量。所以 OrderPosition 知道哪个 Product 被订购了多少次。

我不确定这些实体的 mapping/relation 是否正确,所以我会在这里展示它们:

产品:

class Product
{
    private $id;
    private $price;
    private $title;
    private $orderPositions;

    public function __construct()
    {
        $this->orderPositions = new ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

    public function getPrice()
    {
        return $this->price;
    }

    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function getOrderPositions()
    {
        return $this->orderPositions;
    }

    public function addOrderPosition(OrderPosition $orderPosition)
    {
        $this->orderPositions[] = $orderPosition;
        if ($orderPosition->getProduct() !== $this) {
            $orderPosition->setProduct($this);
        }
        return $this;
    }
}

订单:

class Order
{
    private $id;
    private $orderPositions;

    public function __construct()
    {
        $this->orderPositions = new ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    public function getOrderPositions()
    {
        return $this->orderPositions;
    }

    public function addOrderPosition(OrderPosition $orderPosition)
    {
        $this->orderPositions[] = $orderPosition;
        if ($orderPosition->getOrder() !== $this) {
            $orderPosition->setOrder($this);
        }
        return $this;
    }
}

排序位置:

class OrderPosition
{
    private $id;
    private $quantity;
    private $order;
    private $product;

    public function getId()
    {
        return $this->id;
    }

    public function getQuantity()
    {
        return $this->quantity;
    }

    public function setQuantity($quantity)
    {
        $this->quantity = $quantity;
    }

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

    public function setOrder(Order $order)
    {
        $this->order = $order;
        if ($order->getOrderPositions() !== $this) {
            $order->addOrderPosition($this);
        }
        return $this;
    }

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

    public function setProduct(Product $product)
    {
        $this->product = $product;
        if ($product->getOrderPositions() !== $this) {
            $product->addOrderPosition($this);
        }
        return $this;
    }
}

映射文件:

产品:

MyBundle\Entity\Product:
    type: entity
    table: product
    repositoryClass: MyBundle\Repository\ProductRepository
    oneToMany:
        orderPositions:
            targetEntity: OrderPosition
            mappedBy: product
            cascade: [ "persist" ]
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        price:
            type: float
        title:
            type: string
            length: 255
            column: title

    lifecycleCallbacks: {  }

订单:

MyBundle\Entity\Order:
    repositoryClass: MyBundle\Repository\OrderRepository
    type: entity
    table: order
    oneToMany:
        orderPositions:
            targetEntity: OrderPosition
            mappedBy: order
            cascade: [ "persist" ]
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO

    lifecycleCallbacks: {  }

订单位置:

MyBundle\Entity\OrderPosition:
    repositoryClass: MyBundle\Repository\OrderPositionRepository
    type: entity
    table: order_position
    manyToOne:
        order:
            targetEntity: Order
            inversedBy: orderPositions
            joinColumn:
                name: order_id
                referencedColumnName: id
        product:
            targetEntity: Product
            inversedBy: orderPositions
            joinColumn:
                name: product_id
                referencedColumnName: id
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        quantity:
            type: integer
    lifecycleCallbacks: {  }

创建表单的控制器看起来像:

$order = new Order();

$form = $this->createFormBuilder($order)
        ->add('quantity', OrderPositionType::class)
        ->add('save', SubmitType::class, array('label' => 'Order'))
        ->getForm();

最后一个 OrderPositionType

class OrderPositionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('quantity', IntegerType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'MyBundle\Entity\OrderPosition'
        ));
    }
}

现在,问题是:我怎样才能让订单为每个产品创建一个 quantity 输入字段?

您这样定义类型:

OrderPositionType:

class OrderPositionType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('quantity');
    }
}

订单类型:

class OrderType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('orderPositions', CollectionType::class, [
            'entry_type' => OrderPositionType::class,
            'allow_add' => false,
        ]);

        // Other fields then...
    }
}

和您的控制器:

    // $products = list of products user has selected. You already have it
    $order = new Order();

    foreach ($products as $product) {
        $orderPosition = new OrderPosition($order);
        $orderPosition->setProduct($product);
        $orderPosition->setQuantity(1); // default quantity, just my guess
    }

    $form = $this->createForm(OrderType::class, $order);