Extend the registration form

Your app might require some extra fields to the registration form.

Thanks to the RegistrationFormBuilderEvent event, you can intercept the form builder and customize it as you wish.

Retrieve the form builder

Let's create an event subscriber: src/EventSubscriber/RegistrationFormBuilderEventSubscriber.php.

namespace App\EventSubscriber;

use NumberNine\Event\RegistrationFormBuilderEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

final class RegistrationFormBuilderEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            RegistrationFormBuilderEvent::class => 'build',
        ];
    }

    public function build(RegistrationFormBuilderEvent $event): void
    {
        $event->getBuilder()
            ->add('accountType', ChoiceType::class, [
                'mapped' => false,
                'choices' => [
                    'Free trial' => 'free_trial',
                    'Pro' => 'pro',
                ],
            ])
        ;
    }
}

Override the template

Then you'll need to override the registration form template, as everything can be overriden.

Create a file named src/Component/Account/RegistrationForm/template.html.twig and put this content inside:

{{ form_start(form) }}
    {{ form_row(form.accountType) }} {# <- this is what we override #}
    {{ form_row(form.username) }}
    {{ form_row(form.email) }}
    {{ form_row(form.plainPassword) }}

    <p class="text-gray-500 mb-5">
        <small>
            {% trans with {'%path%': N9_path(PAGE_FOR_PRIVACY)} %}Your personal data will be used to support your experience throughout this website,
            to manage access to your account, and for other purposes described in our <a href="%path%">privacy policy</a>.{% endtrans %}
        </small>
    </p>

    <button class="btn btn-color-primary">{{ 'Register'|trans }}</button>
{{ form_end(form) }}

Here you go.

The form now looks like this:

Overriden registration form

Handle form submission

When the user clicks Register, a new User entity is created, and the user logged in. But our new accountType field is useless.

Now, create a new event subscriber that will intercept the RegistrationFormSuccessEvent event: src/EventSubscriber/RegistrationFormSuccessEventSubscriber.php.

namespace App\EventSubscriber;

use NumberNine\Event\RegistrationFormSuccessEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

final class RegistrationFormSuccessEventSubscriber implements EventSubscriberInterface
{
    public function __construct(
        // inject any service you need
    ) {
    }

    public static function getSubscribedEvents(): array
    {
        return [
            RegistrationFormSuccessEvent::class => 'process',
        ];
    }

    public function process(RegistrationFormSuccessEvent $event): void
    {
        $user = $event->getUser();
        $form = $event->getForm();
        $response = $event->getResponse();

        $accountType = $form['accountType']->getData();

        // Do what you need here, and override the response if needed.
    }
}

WARNING

If you change something in the $user entity and persist it, you'll need to reauthenticate. To authenticate the user, inject NumberNine\Security\UserAuthenticator service and retrieve the new response:

$response = $this->authenticator->authenticateUser($user);
$event->setReponse($response);