I'm trying to make a form with a choice type input on the field roles on my entity user. However, Symfony reply me an error "Array to string conversion error"
My roles don't have to be an array because the are not multiple (role hierarchy in security.yaml).
Here is my Form Builder :
$builder
->add('email')
->add('prenom')
->add('nom')
->add('password', PasswordType::Class)
->add('confirm_password', PasswordType::Class)
->add('roles', ChoiceType::class, [
'choices' => [
'Utilisateur' => "ROLE_USER",
'Valideur' => "ROLE_VALIDEUR",
'Administrateur' => "ROLE_ADMIN",
],
])
And my User entity :
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Assert\Length(min="8", minMessage="Votre mot de passe doit contenir au moins 8 carractères")
*/
private $password;
/**
* @Assert\EqualTo(propertyPath="password", message="Vous n'avez pas tapé le même mot de passe")
*/
private $confirm_password;
/**
* @ORM\Column(type="simple_array")
*/
private $roles = array();
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank
*/
private $prenom;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank
*/
private $nom;
/**
* @ORM\Column(type="string", length=255)
* @Assert\Email()
* @Assert\NotBlank
*/
private $email;
public function getId(): ?int
{
return $this->id;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getConfirmPassword(): ?string
{
return $this->confirm_password;
}
public function setConfirmPassword(string $confirm_password): self
{
$this->confirm_password = $confirm_password;
return $this;
}
public function getRoles(): array
{
return array_unique($this->roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function getPrenom(): ?string
{
return $this->prenom;
}
public function setPrenom(?string $prenom): self
{
$this->prenom = $prenom;
return $this;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(?string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getUsername(): ?string
{
return $this->email;
}
public function eraseCredentials()
{
}
public function getSalt()
{
}
}
Could you explain me where are the problems in my user Entity (or somewhere else) please ?
The problem here is that Symfony trying to convert the value of the choice type to an array for user roles because the choice value is a string
'Utilisateur' => "ROLE_USER"
.
The only solution is to not define a specific entity for the form and after apply values to the user entity.
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// The builder doesn't change
$builder
->add('email')
->add('prenom')
->add('nom')
->add('password', PasswordType::Class)
->add('confirm_password', PasswordType::Class)
->add('roles', ChoiceType::class, [
'choices' => [
'Utilisateur' => 'ROLE_USER',
'Validateur' => 'ROLE_VALIDATEUR',
'Administrateur' => 'ROLE_ADMIN'
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([]);
}
}
class UserController extends AbstractController
{
public function index(Request $request, EntityManagerInterface $manager)
{
// Create the form
$form = $this->createForm(UserType::class);
// Render the Twig file and pass the form as a view
return $this->render('user/index.html.twig', ['form' => $form->createView()]);
}
}
public function index(Request $request, EntityManagerInterface $manager)
{
$form = $this->createForm(UserType::class);
// Processing the form from the request
$form->handleRequest($request);
// Check if form is submitted
if($form->isSubmitted()) {
// Fetch data from the form
$data = $form->getData();
// Create user from data
$user = (new User)
->setEmail($data['email'])
->setPrenom($data['prenom'])
->setNom($data['nom'])
->setPassword($data['password'])
->setConfirmPassword($data['confirm_password'])
// Here, we convert the string to an array
->setRoles([$data['roles']]);
// Add the user to the database
$manager->persist($user);
$manager->flush();
}
return $this->render('user/index.html.twig', ['form' => $form->createView()]);
}
$manager->flush()
). The following code is the correction (we can use the validator to check if an entity is valid):// Request validator as injection dependency
public function index(Request $request, EntityManagerInterface $manager, ValidatorInterface $validator)
{
$form = $this->createForm(UserType::class);
// Set default values for validation variables
$violations = null;
$conflict = false;
$form->handleRequest($request);
if($form->isSubmitted()) {
$data = $form->getData();
$user = (new User)
->setEmail($data['email'])
->setPrenom($data['prenom'])
->setNom($data['nom'])
->setPassword($data['password'])
->setConfirmPassword($data['confirm_password'])
// Here, we convert the string to an array
->setRoles([$data['roles']]);
// Get violations from the user entity with the 'validate' function
$violations = $validator->validate($user);
// Check if there are no violations. If it is, the user is valid
if($violations->count() === 0) {
$manager->persist($user);
// Catch a unique constraint violation exception during flushing
try {
$manager->flush();
} catch(UniqueConstraintViolationException $e) {
$conflict = true;
}
}
}
return $this->render('user/index.html.twig', [
'form' => $form->createView(),
// Pass violations and conflict
'violations' => $violations,
'conflict' => $conflict
]);
}
I hope that I help you!
If you want create a field where we can select multiple roles, this link may help you (the website is French).