I have an entity 'administration' which has a field 'firstPeriod'. This field is not nullable (neither in the class definition nor in the database) and nor should it be, as this field should never ever be empty, the application would fail.
However, this field does not have a default value because if an oblivious user would simply submit the form without changing the default value, chaos would ensue. The user must make a conscious choice here. There is validation in place to ensure the field is not empty and within accepted range.
When I try to render the form, the 'propertyAccessor' of the formbuilder component throws this exception:
Type error: Return value of AppBundle\Entity\Administration::getFirstPeriod() must be of the type integer, null returned
It looks like the formbuilder tries to get the value of the field before it is set, which ofcourse leads to said exception.
How can I handle this situation so that the form will render without providing the user with a default value?
To further clarify: Null is not okay, but neither is any default I can provide, the user must make a conscious decision. The same goes for any dev that instantiates this entity directly. It must be provided before the entity is persisted, but I cannot give a default because if the default is left as it is, the application will not function 12 out of 13 times.
- If I allow null on the entity field "?int" I'm effectively making a field nullable that should never be null
- If I provide a default, the default might be accepted blindly, which would lead to wrong results further on in the application that are very hard to spot for most users.
- I've already tried to set the 'empty_data => 0' in the formType, to no avail
sorry for the mess below, the 'Code Sample' does not handle this code well
My (truncated) entity:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** * Administration * * @ORM\Table(name="administration") * @ORM\Entity(repositoryClass="AppBundle\Repository\AdministrationRepository") */ class Administration { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="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 (truncated) formType (as best as i could get it formatted here):
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';
}
}
My controller:
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
]);
}
}
My validation:
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'