Symfony Form EntityType

时间:2018-05-13 11:32:06

标签: forms symfony entity formbuilder

我正在构建一个简单的产品页面。有些产品可能有一些额外的选项(productOptions)。由于选择框,可以选择这些选项。但问题如下:

我有以下实体:

产品

#src/appbundle/entity
<?php
/**
 * Product
 */

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository")
 * @ORM\Table(name="product")
 */
class Product {

    /**
     * @var string id
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @var string title
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @var ArrayCollection|ProductOption[]
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductOption", mappedBy="product", fetch="EAGER")
     */
    protected $productOptions;
    protected $tempProductOptions;

    /**
     * @return string
     */
    public function getId() {
        return $this->id;
    }

    /**
     * @return string
     */
    public function getTitle() {
        return $this->title;
    }

    /**
     * @param string $title
     */
    public function setTitle($title) {
        $this->title = $title;
    }

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

    public function addProductOption(ProductOption $productOption){
        if($this->productOptions->contains($productOption)){
            return;
        }

        $productOption->setProduct($this);
        $this->productOptions->add($productOption);
    }

    public function removeProductOption(ProductOption $productOption){
        if(!$this->productOptions->contains($productOption)){
            return;
        }

        $productOption->setProduct(null);
        $this->productOptions->removeElement($productOption);
    }

    /**
     * @return ProductOption[]|ArrayCollection
     */
    public function getProductOptions() {
        return $this->productOptions->toArray();
    }

}

ProductOption

#src/appbundle/entity
<?php
/**
 * ProductOption
 */

namespace AppBundle\Entity;

use AppBundle\Repository\GenusRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductOptionRepository")
 * @ORM\Table(name="product_option")
 */
class ProductOption {

    /**
     * @var int id
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @var string title
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @var float price
     * @ORM\Column(type="float", scale=2)
     */
    protected $price;

    /**
     * ProductOption connected to specific product
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="productOptions")
     * @ORM\JoinColumn(nullable=false)
     */
    protected $product;

    /**
     * @return int
     */
    public function getId() {
        return $this->id;
    }

    /**
     * @param int $id
     */
    public function setId($id) {
        $this->id = $id;
    }

    /**
     * @return string
     */
    public function getTitle() {
        return $this->title;
    }

    /**
     * @param string $title
     */
    public function setTitle($title) {
        $this->title = $title;
    }

    /**
     * @return float
     */
    public function getPrice() {
        return $this->price;
    }

    /**
     * @param float $price
     */
    public function setPrice($price) {
        $this->price = $price;
    }

    /**
     * @return Product
     */
    public function getProduct() {
        return $this->product;
    }

    /**
     * @param Product $product
     */
    public function setProduct($product) {
        $this->product = $product;
    }

    public function __toString() {
        return (string)$this->getTitle() . '(&euro;'.$this->getPrice().')';
    }
}

这是我的ProductType(formbuilder)

#src/appbundle/form
<?php

namespace AppBundle\Form;

use AppBundle\Entity\Product;
use AppBundle\Entity\ProductOption;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ProductType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('title', TextType::class, [
            'label' => 'titel'
        ]);

        $builder->add('tempProductOptions', EntityType::class, [
            'class' => ProductOption::class,
            'multiple' => true,
            'expanded' => true,
            'mapped' => false,
            'choice_attr' => function($productOption, $key, $index) {
                /** @var ProductOption $productOption */
                return [
                    'data-price' => $productOption->getPrice(),
                ];
            },
        ]);

        $builder->add('save', SubmitType::class, array(
            'label' => 'Opslaan'
        ));
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'data_class' => Product::class,
        ));
    }

    public function getBlockPrefix() {
        return 'product';
    }
}

Twig文件 这是一个非常基本的例子

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1>test product page</h1>

{{ dump(form) }}

{{ form_start(form) }}
    {{ form_row(form.titel) }}
    {{ form_row(form.productOptions) }}
    {{ form_row(form.save) }}
{{ form_end(form) }}
</body>
</html>

对于exmaple产品1有两个选项:

  • 选项1(50欧元)
  • 选项2(60欧元)

在数据库中,选项1和2连接到产品1 table product_option

ID标题价格product_id

1选项1 50 1

2选项2 60 1

但是在视图中已经检查了选项(因为它们通过db连接)。是否可以取消选中复选框。

简短版。每种产品都有额外的选择。这些选项存储在db中。在产品页面上创建表单时,用户可以选择这些选项,但已经检查过它们。

还在我的formbuilder

中添加了以下内容
public function finishView(FormView $view, FormInterface $form, array $options) {
    foreach ($view->children['productOptions']->children as $productOption) {
        $productOption->vars['checked'] = false;
    }
}

但仍在检查复选框

我找到了解决方案:

public function buildForm(FormBuilderInterface $builder, array $options) {
        // arraycollection with productOptions
        $productOptions = $options['data']->getProductOptions();

        $builder->add('id', HiddenType::class, ['mapped' => false]);
        $builder->add('productOptions', ChoiceType::class, [
            'choices'  => $productOptions,
            'expanded' => true,
            'multiple' => true,
            'mapped' => false,
            'choice_value' => function (ProductOption $productOption) {
                return $productOption->getId();
            },
            'choice_label' => function(ProductOption $productOption, $key, $index) {
                return $productOption->__toString();
            },
            'choice_attr' => function(ProductOption $productOption, $key, $index) {
                return [
                    'data-prijs' => $productOption->getPrijs(),
                ];
            },
        ]);
   // rest here ...

0 个答案:

没有答案