Symfony4: динамическая форма с коллекцией (типом) ChoiceType с дополнительными требованиями - PullRequest
0 голосов
/ 29 октября 2019

Извините, ребята, я чувствую себя слишком глупо, чтобы понять эту часть документации Symfony 4. Я хочу создать форму для создания и редактирования набора данных со связанными подмножествами (обычно это не проблема).

Первый объект называется Case (для этого вопроса только одно свойство).

<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CaseRepository")
 */
class Case
{
   // [...]

    /**
     * @ORM\Column(type="text", nullable=false)
     * @Assert\NotNull()
     * @var string
     */
    private $title;

    // [...]

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\CaseForecast", mappedBy="case",  cascade={"persist", "remove"},orphanRemoval=true)
     */
    private $caseForecasts;


    public function __construct()
    {
        // [...]
        $this->caseForecasts = new ArrayCollection();
    }

    // [...]

    /**
     * @return Collection|CaseForecast[]
     */
    public function getCaseForecasts(): Collection
    {
        return $this->caseForecasts;
    }

    public function addCaseForecastis(CaseForecast $caseForecastis): self
    {
        if (!$this->caseForecasts->contains($caseForecastis)) {
            $this->caseForecasts[] = $caseForecastis;
            $caseForecastis->setCase($this);
        }
        return $this;
    }

    public function removeCaseForecastis(CaseForecast $caseForecastis): self
    {
        if ($this->caseForecasts->contains($caseForecastis)) {
            $this->caseForecasts->removeElement($caseForecastis);
            // set the owning side to null (unless already changed)
            if ($caseForecastis->getCase() === $this) {
                $caseForecastis->setCase(null);
            }
        }
        return $this;
    }
}

Важное отношение в это время - CaseForecast. Это отношение ManyToOne. Это сущность:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CaseForecastRepository")
 */
class CaseForecast
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Case", inversedBy="caseForecasts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $case;

    /**
     * @ORM\Column(type="integer")
     */
    private $itemNumber;

    /**
     * @ORM\Column(type="integer", options={"comment":"0 secure; 1 fragile; 2 reject"})
     *
     */
    private $forecast;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $comment;

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

    public function getCase(): ?Case
    {
        return $this->case;
    }

    public function setCase(?Case $case): self
    {
        $this->case = $case;

        return $this;
    }

    public function getItemNumber(): ?int
    {
        return $this->itemNumber;
    }

    public function setItemNumber(int $itemNumber): self
    {
        $this->itemNumber = $itemNumber;
        return $this;
    }

    public function getForecast(): ?int
    {
        return $this->forecast;
    }

    public function setForecast(int $forecast): self
    {
        $this->forecast = $forecast;
        return $this;
    }

    public function getBegruendung(): ?string
    {
        return $this->begruendung;
    }

    public function setBegruendung(?string $begruendung): self
    {
        $this->begruendung = $begruendung;
        return $this;
    }

    public function __toString()
    {
        return $this->zahnNummer;
    }
}

Свойство itemNumber получило диапазон значений 11..18,21..28,31..38,41..48 Одна сущность Case получила 32 CaseForecast в виде ArrayCollection...каждый раз! Когда я создаю объект Case, я также создаю 32 объекта CaseForecast. Свойство «прогноз» представляет собой целочисленное значение 0,1 или 2.

Форма должна выглядеть следующим образом: Форма с коллекцией типов выбора

То, что вы видите нарисунок:С левой стороны переведены значения для прогноза. Затем следует CaseForecast.forecast для позиций №№ 11-18 и 28-21. В следующей «строке» вы увидите itemNumbers в две строки. Следующая строка CaseForecast для itemNumbers 41-48 и 38-31(да, вы правы, все дело в зубном протезе)

На первом шаге я создал форму вручную, потому что схема данных была другой (широкая таблица / большой объект с 32). Теперь мне пришлось изменить схему данных, и теперь наступил момент, когда я сдаюсь.

Мой FormType выглядит следующим образом:

<?php

namespace App\Form;

use App\Entity\Case;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class CaseShortType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('titel', TextType::class, [
                'label' => "Title",
                'attr' => [
                    'tab-index' => 1
                ]
            ])
            ->add('caseForecasts', CollectionType::class, [
                'entry_type' => ChoiceType::class,
                'entry_options' => [
                    'choices' => [
                        'secure' => 0,
                        'fragile' => 1,
                        'reject' => 2
                    ],
                    'expanded' => true,
                ],
                'allow_add' => false,
                'allow_delete' => false,
            ])
            ->add("submit", SubmitType::class, [
                'label' => 'save',
                'attr' => ['class' => "btn btn-primary"]
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Case::class,
            'aktion' => null
        ]);
    }
}

Я пробовал несколько учебных пособий и документации на symfony.com,stackoverflow и т. д. Я сделал и вроде депрессии. Ничто не подходит, даже приблизительное (для меня).

Что я хочу:

  • Я хочу создать форму с экрана выше с этой схемой отношений.
  • Я хочу сделать это "symfony-way", а не вручную.
  • Когда я редактирую «Case», я хочу, чтобы варианты были предварительно проверены со значением из CaseForecast.forecast (обратный вызов на choice_value? Как получить доступ к текущему CaseForecast?)
  • Я хочу itemNumber какключ для массива CollectionType (если он не работает таким образом, я должен перевести это).

Может быть, у вас есть несколько советов для некоторых других HowTos и документации ...

Спасибо!

1 Ответ

0 голосов
/ 30 октября 2019

Я решил это самостоятельно, спасибо за перечисление.

  1. Я создал сущность с 3 решениями, изменив ChoiceType на EntityType. Примеры, которые я нашел, всегда основаны на EntityType. Поэтому я использовал это.
  2. Я создал ForecastType для отдельного элемента коллекции и добавил EventListener для «проверенного» сравнения
  3. Для макета я добавил собственную тему формы для подчиненной формыпрогнозов.
  4. Я изменил шаблон формы, чтобы разбить коллекцию на блоки:
{% for forecast in form.caeForecasts %}
    {% if forecast.vars.value.itemNumber<30 %}
        {{ form_widget(forecast) }}
    {% endif %}
{% endfor %}

Вот и все. Когда я отправляю форму и обрабатываю запрос, все находится в том месте, где оно принадлежит:)

...