On my form, I am using novalidate
attribute like this :
{{ form_start(form, {'attr': {novalidate: 'novalidate'}}) }}
To disable HTML5 browser validation. So Symfony assert errors appears. On the new.html.twig page it works perfectly fine! The novalidate attribute disable the html5 validation and the assert errors appear.
But when I use the novalidate attribute on edit.html.twig and leave the username
field empty (i don't fill it on the form) the @Assert\NotBlank()
doesn't work. And I get this error
Expected argument of type "string", "null" given at property path "username".
Why symfony assert work on the new page, but it doesnt work on the edit page? By the way, i am not using any validation groups.
here is the code of my User entity(without getters and setters) :
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
* @Assert\Email()
* @Assert\NotBlank()
*/
private $email;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
*/
private $username;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank()
* @Assert\Length(
* min = 8, max = 30,
* minMessage = "Your password must be between 6 and 30 characters.")
*/
private $password;
/**
* @ORM\Column(type="json", nullable=true )
*/
private $roles = [];
Here is the code of the form :
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class )
->add('username', TextType::class)
->add('password',PasswordType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
both of new.html.twig and edit.html.twig have the same code :
{{ form_start(form, {'attr': {novalidate: 'novalidate'}}) }}
{{ form_widget(form.email, {'attr': {'class': 'form-control',placeholder: 'Email Adress'} }) }}
{{form_errors(form.email)}}
{{ form_widget(form.username, {'attr': {'class': 'form-control',placeholder: 'Username'} }) }}
{{form_errors(form.username)}}
{{ form_widget(form.password, {'attr': {'class': 'form-control'} }) }}
{{form_errors(form.password)}}
<button class="btn btn-success">Submit</button>
{{ form_rest(form) }}
{{ form_end(form) }}
Controller code :
/**
* @Route("/new", name="user_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('user_index');
}
return $this->render('user/new.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}/edit", name="user_edit", methods={"GET","POST"})
*/
public function edit(Request $request, User $user): Response
{
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('user_index');
}
return $this->render('user/edit.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}
my getters and setters :
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
I think you should add
?
sign to the string type on your all setters.For example change it From
setUsername(string $username): self
TosetUsername(?string $username): self
This should fix the assert problem on the edit page.