Я создаю простую страницу продукта. Некоторые продукты могут иметь дополнительные параметры (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';
}
}
Файл ветки
это очень простой пример
<!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>
Для примера продукта 1 есть два варианта:
- вариант 1 (50 евро)
- вариант 2 (60 евро)
В базе данных опции 1 и 2 подключены к продукту 1
таблица product_option
ID название цена product_id
1 вариант 1 50 1
2 вариант 2 60 1
Но в представлении опции уже проверены (потому что они подключены через 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 ...