FriendsOfSymfony / FOSUserBundle

Provides user management for your Symfony project. Compatible with Doctrine ORM & ODM, and custom storages.
https://symfony.com/doc/master/bundles/FOSUserBundle/index.html
MIT License
3.24k stars 1.57k forks source link

Override Registration Controller #2837

Open wuxian-wifi opened 6 years ago

wuxian-wifi commented 6 years ago

Hello,

I tried to override the registration controller for adding some custom fields, like register date. But I have some problems:

"Cannot autowire service "fos_user.registration.form.factory": argument "$name" of method "FOS\UserBundle\Form\Factory\FormFactory::__construct()" has no type-hint, you should configure its value explicitly."

app/config/services.yaml:

fos_user.registration.form.factory:
     class: FOS\UserBundle\Form\Factory\FormFactory

app/config/routes.yaml:

fos_user.registration:
    path: /register
    defaults:
        _controller: App\Controller\RegistrationController::registerAction

app/Controller/RegistrationController:

<?php

namespace App\Controller;

use FOS\UserBundle\Controller\RegistrationController as FOSController;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Form\Factory\FactoryInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class RegistrationController extends FOSController
{
    public function __construct()
    {

    }

    public function registerAction(Request $request)
    {
        $eventDispatcher = $this->get('event_dispatcher');
        $formFactory = $this->get('fos_user.registration.form.factory');
        $userManager = $this->get('fos_user.user_manager');

        $user = $userManager->createUser();
        $user->setEnabled(true);

        $event = new GetResponseUserEvent($user, $request);
        $eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);

        if (null !== $event->getResponse()) {
            return $event->getResponse();
        }

        $form = $formFactory->createForm();
        $form->setData($user);

        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            if ($form->isValid()) {
                $event = new FormEvent($form, $request);
                $eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

                $register_date = date_create(date('Y-m-d H:i:s'));
                $user_id = "000000000000001";
                $roles = ["ROLE_USER"];

                $user->setDateRegister($register_date);
                $user->setUserId($user_id);
                $user->setRoles($roles);

                $userManager->updateUser($user);

                if (null === $response = $event->getResponse()) {
                    $url = $this->generateUrl('fos_user_registration_confirmed');
                    $response = new RedirectResponse($url);
                }

                $eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

                return $response;
            }

            $event = new FormEvent($form, $request);
            $this->$eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);

            if (null !== $response = $event->getResponse()) {
                return $response;
            }
        }

        return $this->render('@FOSUser/Registration/register.html.twig', array(
            'form' => $form->createView(),
        ));
    }
}

Thank you in advance :)

si4kar commented 6 years ago

App\Controller\RegistrationController: arguments: $formFactory: '@fos_user.registration.form.factory'

Change services.yaml

stof commented 6 years ago

Well, why are you trying to define your own form facotry services if you override the controller ?

si4kar commented 6 years ago

In Symfony 4 I have such error, when i try to overwrite the register controller:

Cannot autowire service "App\Controller\RegisterController": argument "$formFactory" of method "__construct()" references interface "FOS\UserBundle\Form\Factory\FactoryInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "fos_user.profile.form.factory", "fos_user.registration.form.factory", "fos_user.change_password.form.factory", "fos_user.resetting.form.factory".

devcut commented 5 years ago

Hi @si4kar, i defined the controller in services.yaml but my function not working.. (I use symfony 4.2)

App\Controller\RegistrationController:
    arguments:
        $formFactory: '@fos_user.registration.form.factory'
<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\HttpFoundation\Request;

class RegistrationController extends BaseController
{
    public function registerAction(Request $request)
    {
        dd('oko');
    }
}

Have you an idea ?

Thanks

tlorens commented 5 years ago

Symfony 4.2 uses DI. You should be able to define all the interfaces/factories in your controller _construct().. add them to the use clauses. Should just work if you have autowiring set to true.

I just had to do this with our legacy app. You have to do some work in 3.4... YMMV

services.yml

    MyUserBundle\Controller\RegistrationController:
        tags: ['controller.service_arguments']
        arguments:
            $eventDispatcher: '@event_dispatcher'
            $formFactory: '@fos_user.registration.form.factory'
            $userManager: '@fos_user.user_manager'
            $tokenStorage: '@security.token_storage'

In your controller.

use FOS\UserBundle\Form\Factory\FactoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

    public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager, TokenStorageInterface $tokenStorage)
    {
        $this->eventDispatcher = $eventDispatcher;
        $this->formFactory     = $formFactory;
        $this->userManager     = $userManager;
        $this->tokenStorage    = $tokenStorage;
    }
joseadame commented 3 years ago

Hi, I've the same problem than @si4kar in symfony 4.4. How I can override registrationController?

FireLizard commented 3 years ago

Hi @joseadame and @si4kar , you could configure this working definition:

# app/config/services.yaml

fos_user.registration.controller:
    class: App\Application\UserBundle\Controller\RegistrationController

FOS\UserBundle\Form\Factory\FactoryInterface: '@fos_user.registration.form.factory'

(Source: Using Aliases to Enable Autowiring)