Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony: Form issue using Return type hinting in Doctrine Entity methods

I was being exceptionally diligent today and decided to return-type hint all of my symfony entity methods. So:

<?php

Class User {
    private string $username;
    public method getUsername(): string {}
}

all good and well, until I made a form to create a new user:

$user = new User();
$this->createForm(SignupType::class, $user);

when the form is displayed, Symfony automatically gets the properties of this new instance of User $user. But since it is a new instantiation, its username property is of course still null, which is an incorrect return type as it needs to be string.

Should I either:

  1. have no return-type hinting in Symfony entities (meh);
  2. set $username = '' (but hat kind of defeats the purpose of not allowing blanks and I can see all sorts of errors evolving); or
  3. unmap the field on the symfony form
  4. other possible solutions...
like image 913
bluppfisk Avatar asked May 14 '17 01:05

bluppfisk


People also ask

What is an entitytype field in doctrine?

EntityType Field¶. A special ChoiceType field that's designed to load options from a Doctrine entity. For example, if you have a Category entity, you could use this field to display a select field of all, or some, of the Category objects from the database.

Should I let Symfony guess my field type without validation?

This is superficial and independent of validation. At best, if you let Symfony guess your field type, then the value of this option will be guessed from your validation information. The required option also affects how empty data for each field is handled.

What is the default entity manager name in doctrine?

This can be a fully-qualified class name (e.g. App\Entity\Category ) or the short alias name (as shown prior). type: string | Doctrine\Persistence\ObjectManager default: the default entity manager

How to define a custom type in doctrine?

When defining a custom type, you should use the ChoiceList class helper: See the "choice_loader" option documentation. In the EntityType, this is overridden to use the id by default. When the id is used, Doctrine only queries for the objects for the ids that were actually submitted.


2 Answers

If an Entity Property cannot be null (and you use PHP 7.1+), then applying the nullable return type declaration sounds more like a dirty and fast workaround to maintain a direct data binding between Entities and Forms (using the Symfony Form Component).

A better global approach (in my opinion) is to decouple the Form data binding from your Doctrine Entities using a DTO (Data Transfer Object), that is a simple POPO (Plain Old PHP Object) to contain your form data.

Using a DTO will allow you to maintain a strict type hinting in your Doctrine Entities (no loss of data consistency) and will decouple Form data binding (but also data validation) from your Entities.

DTO's allows reusability and have many other advantages.

Some useful references about the use of DTO's with Symfony Forms:

  • Avoiding Entities in Forms (by Iltar van der Berg)
  • Rethinking Form Development (by Iltar van der Berg)
  • Symfony Forms 101 (by Bernhard Schussek the creator of the Form component)
  • Don't Use Entities in Symfony Forms. Use Custom Data Objects Instead
  • Entities should always be valid
like image 145
gp_sflover Avatar answered Oct 08 '22 01:10

gp_sflover


If you're using PHP 7.0, which has no nullable return type declaration support, the first option will be the right (non-hacky) choice. In case of you're using PHP 7.1+, you can define a nullable return type declaration.

<?php

class User 
{
    public function getUsername(): ?string {}
}
like image 39
Mikhail Prosalov Avatar answered Oct 08 '22 01:10

Mikhail Prosalov