我正在构建一个简单的产品页面。有些产品可能有一些额外的选项(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() . '(€'.$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和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 ...