Symfony Form EntityType - PullRequest
       22

Symfony Form EntityType

0 голосов
/ 13 мая 2018

Я создаю простую страницу продукта. Некоторые продукты могут иметь дополнительные параметры (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';
    }
}

Файл ветки это очень простой пример

<!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 ...
...