Нулевые значения в новых сущностях в формах Symfony 3.4 без значений по умолчанию - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть объект «администрация», который имеет поле «первый период».Это поле не имеет значения NULL (ни в определении класса, ни в базе данных) и не должно быть, так как это поле никогда не должно быть пустым, приложение не сможет работать.

Однако это поле не имеетзначение по умолчанию, потому что, если забывший пользователь просто отправит форму без изменения значения по умолчанию, наступит хаос.Пользователь должен сделать здесь сознательный выбор.Существует проверка, чтобы убедиться, что поле не пустое и находится в допустимом диапазоне.

Когда я пытаюсь отобразить форму, свойство propertyAccessor компонента formbuilder выдает это исключение:

Ошибка типа: возвращаемое значение AppBundle \ Entity \ Administration :: getFirstPeriod () должно иметь тип integer, возвращается ноль

Похоже, что formbuilder пытается получить значение поля до того, какУстанавливается, какой курс приводит к указанному исключению.

Как я могу обработать эту ситуацию, чтобы форма отображалась без предоставления пользователю значения по умолчанию?

Для дальнейшего уточнения: Null не в порядке, но я не могу предоставить ни одно значение по умолчанию, пользователь должен принять осознанное решение.То же самое касается любого разработчика, который создает экземпляр этой сущности напрямую.Он должен быть предоставлен до того, как сущность будет сохранена, но я не могу дать значение по умолчанию, потому что если оставить значение по умолчанию таким, как оно есть, приложение не будет работать 12 из 13 раз.

  • Если я разрешу нольв поле сущности "? int" я фактически делаю поле, допускающее значение NULL, равное , которое никогда не должно быть равным нулю
  • Если я предоставлю значение по умолчанию, значение по умолчанию может быть принято вслепую, что приведет кдальнейшие неправильные результаты в приложении, которые очень трудно обнаружить большинству пользователей.
  • Я уже пытался установить 'empty_data => 0' в formType, но безрезультатно

извините за беспорядок, приведенный ниже, "Пример кода" плохо обрабатывает этот код

Моя (усеченная) сущность:

namespace AppBundle\Entity;

use Doctrine \ORM \ Mapping as ORM;

/ ** * Администрирование * * @ORM \ Table (name = "Administration") * @ORM \ Entity (repositoryClass = "AppBundle \ Repository \ AdministrationRepository") * / class Administration{/ ** * @var int * * @ORM \ Column (name = "id", типe = "integer") * @ORM \ Id * @ORM \ GeneratedValue (стратегии = "AUTO") * / private $ id;

/**
 * @var int
 *
 * @ORM\Column(name="first_period", type="smallint", nullable=false)
 */
private $firstPeriod;

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


/**
 * @return int
 */
public function getFirstPeriod(): int
{
    return $this->firstPeriod;
}

/**
 * @param int $firstPeriod
 */
public function setFirstPeriod(int $firstPeriod): void
{
    $this->firstPeriod = $firstPeriod;
}

}

My (усеченный) formType(как можно лучше отформатировать его здесь):

    public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('firstPeriod', null, [
            'label' => 'First period'
        ])
    ;
}

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

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

}

Мой контроллер:


namespace AppBundle\Controller\Admin;

class AdministrationController extends Controller
{
    public function editAction(
        EntityManager $em,
        Router $router,
        Security $security,
        Session $session,
        LoggerInterface $logger,
        Request $request,
        Administration $administration = null
    ): Response {

        if ($administration === null) {
            $new = true;
            $administration = new Administration();
            $pageTitle = 'New';
        } else {
            $new = false;
            $pageTitle = 'Edit';
        }
        $breadcrumbs->add($crumbs);

        $form = $this->createForm(AdministrationType::class, $administration);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            /** @var Administration $administration */
            $administration = $form->getData();

            try {
                $em->persist($administration);
                $em->flush();
            } catch (ORMException $e) {
                $logger->critical($e->getMessage());

                $session->getFlashBag()->add('error', 'Database error.');

                if ($new) {
                    return $this->redirectToRoute('administration_new');
                } else {
                    return $this->redirectToRoute(
                        'administration_edit',
                        ['administration' => $administration->getId()]
                    );
                }
            }

            $session->getFlashBag()->add('success', 'Success!');

            return $this->redirectToRoute('administration_index');
        }

        return $this->render(':Admin/Administration:edit.html.twig', [
            'administrationForm' => $form->createView(),
            'pageTitle' => $pageTitle
        ]);
    }
}

Моя проверка:

AppBundle\Entity\Administration:
properties:
    firstPeriod:
        - NotBlank:
              message: 'adm.firstperiod.empty'
        - Range:
              min: 1
              max: 13
              minMessage: 'adm.firstperiod.too_low'
              maxMessage: 'adm.firstperiod.too_high'

1 Ответ

0 голосов
/ 13 декабря 2018

Поскольку форма Symfony использует средства доступа к свойствам, как говорит @Cerad, вы можете добавить в форму несопоставленное поле и получить / установить поле в событиях формы, добавив специальный метод для получения неинициализированного $ first_period ...

Пример кода может быть ...

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

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

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

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

    public function getFirstPeriod(): int
    {
        return $this->first_period;
    }

    public function setFirstPeriod(int $first_period): self
    {
        $this->first_period = $first_period;

        return $this;
    }

    public function getFirstPeriodOrNull(): ?int
    {
        return $this->first_period;
    }
}

Форма

<?php

namespace App\Form;

use App\Entity\Administration;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class AdministrationType extends AbstractType
{ 
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('first_period', null, [
                'mapped' => false,
                'required' => false,
            ])
            ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
                /** @var Administration */
                $a = $event->getData();

                $event->getForm()->get('first_period')->setData($a->getFirstPeriodOrNull());

            })
            ->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
                $f = $event->getForm()->get('first_period')->getData();

                if (is_int($f)) {
                    /** @var Administration */
                    $a = $event->getData();
                    $a->setFirstPeriod($f);
                }
            });
        ;
    }

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

Это прекрасно работает в Symphony 4.2

...