skip to Main Content

PHP 8.2-apache (Docker image)

Xdebug enabled
Symfony 6.4

Quick summary
I am creating form in Symfony 6.4 Framework and when it is submitted and request is handled, it tries to get value of unset entity, so it could set it. This problem is present only if data_class is specified, otherwise it gives an array without a problem. Mapping to the entity is a problem though.

In more detail

I am creating form in a standard Symfony way using a class

<?php 

...

#[ORMEntity(repositoryClass: UserRepository::class)]
#[UniqueEntity(fields: ['username'], message: 'There is already an account with this username')]
class User extends AbstractADUCEntity implements UserInterface, PasswordAuthenticatedUserInterface
{
    use UuidV7;
    use Username;
    use Password;
    use Vocative;
    use FullName;
    use Email;


    public function getRoles(): array
    {
        return [];
    }

    public function eraseCredentials(): void {}

    public function getUserIdentifier(): string
    {
        return $this->getUsername();
    }
}

here my php traits are always the property, getter and setter, e.g. use Username gives the class this:

<?php 

use DoctrineORMMapping as ORM;

trait Username
{
    #[ORMColumn(unique: true)]
    private string $username;

    public function getUsername(): string
    {
        return $this->username;
    }

    public function setUsername(string $username): static
    {
        $this->username = $username;
        return $this;
    }
}

The form is then make as a class

<?php 

...

class SignUpType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('firstName', TextType::class, [
                'attr' => [
                    'placeholder' => 'Křestní jméno',
                    'data-field-name' => 'firstName',
                    'data-action' => 'keyup->sign-up#processControl'
                ],
            ])
            ...
        ;
    }

In this scenario everything works and the result after sending the form is sent form

My SecurityController is very straightforward at this time:

<?php
...

class SecurityController extends AbstractController
{
    #[Route('registrace', name: 'sign_up', methods: ['HEAD', 'GET', 'POST'])]
    public function signUp(Request $request): Response
    {
        $form = $this->createForm(SignUpType::class);
        $form->handleRequest($request);

        dump($form->getData());
        if ($form->isSubmitted() && $form->isValid()) {
            die();
        }


        return $this->render('security/sign-up.html.twig', [
            'sign_up_form' => $form,
        ]);
    }
}

Although if I add code into SignUpType

<?php 
...
     
public function configureOptions(OptionsResolver $resolver): void
{
    $resolver->setDefaults([
        'data_class' => User::class,
    ]);
}

sent form with data_class

This error is present for all properties of the User entity.

I have tried to downgrade Symfony version, since I am using version 6.4 in development, but the problem also prevailed on stable version 6.3.

Using xdebug I managed to find the path how the getter is called.
The Xdebug trace

I believe the problem starts within the setValue that tries to getValue before setting the object. enter image description here

One obvious way would be to set default values of all properties to empty strings '', but I do not like this solution since the object is really not initialized, thus I believe it should not have values that are not default.

I also tried to get rid of the traits and do this on a different entity with only one column, made by symfony maker. The story is the same, so it is not caused by the trait system I am using for doctrine entities.

And here I got stacked, not sure how to proceed from here.

One interesting behavior

While making the POST request with specified data_class, I run the xdebug and I found that the method handleRequest is going smoothly without a problem. But when I do not put breakpoint in the handleRequest method, but rather into the getter of username, we can see that it is going from handleRequest further. It seems to me like it would go two different paths, one when I see the xdebug in the process, and one when I put the breakpoint to the end in the getter. I am not able to explain this.

Edit: If I scroll few kilometers down below those errors, there is actually my dump with good entity. Therefore something else must be going on than creation of this entity.
enter image description here

Also if I run it without dd, it will fall on error "headers are already been sent". But I am not using any dump anywhere else.

2

Answers


  1. Chosen as BEST ANSWER

    I have found the answer, so I want everyone to know, if headed the same way. The reason was xdebug settings that I would not image it could be.

    My configuration file is

    zend_extension=xdebug
    
    error_reporting=E_NONE
    display_errors=off
    
    [xdebug]
    xdebug.mode=develop,debug
    xdebug.client_host=host.docker.internal
    xdebug.client_port=9003
    xdebug.idekey="PHPSTORM"
    ;xdebug.show_error_trace=1
    xdebug.start_with_request=yes
    xdebug.discover_client_host=1
    xdebug.log_level=0
    

    The commented line xebug.show_error_trace=1 caused this. I do not know why, but commenting it is the solution. Xdebug still works and now even the Symfony is acting like it should.


  2. You have not initialized a User object. Look closely at the example in the docs. Start by creating a new User() and pass it to the createForm method.

    class SecurityController extends AbstractController
    {
        #[Route('registrace', name: 'sign_up', methods: ['HEAD', 'GET', 'POST'])]
        public function signUp(Request $request): Response
        {
            $newUser = new User();
            $form = $this->createForm(SignUpType::class, $newUser);
            $form->handleRequest($request);
    
            if ($form->isSubmitted() && $form->isValid()) {
                // ToDo: persist the $newUser
                dump($newUser->getUsername());
    
                // $form->getData() holds the submitted values
                // but, the original `$task` variable has also been updated
                $newUser = $form->getData();
                dump($newUser->getUsername());
    
                die();
    
                // ... perform some action, such as saving the task to the database
            }
    
    
            return $this->render('security/sign-up.html.twig', [
                'sign_up_form' => $form,
            ]);
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search