无法解析 symfony 4.3 中覆盖 FOS 控制器的参数 $token

Posted

技术标签:

【中文标题】无法解析 symfony 4.3 中覆盖 FOS 控制器的参数 $token【英文标题】:Could not resolve argument $token on override FOS Controller in symfony 4.3 【发布时间】:2020-01-17 23:15:42 【问题描述】:

首先,我尝试了与该主题相关的所有问题和答案。此外,我尝试了相关问题并尝试解决它但没有成功。所以请仔细阅读我的问题。

我想覆盖 FOS 控制器。我成功重定向但没有得到完美的 /register/confirm/token 工作。 我收到一个令牌错误。

出现错误: 无法解析“App\Controller\RegistrationController::confirmaction()”的参数 $token,也许您忘记将控制器注册为服务或错过使用“controller.service_arguments”标记它?

我的代码

RegistrationController.php

<?php

/*
 * This file is part of the FOSUserBundle package.
 *
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace App\Controller;

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\UserManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;


class RegistrationController extends \FOS\UserBundle\Controller\RegistrationController

    private $eventDispatcher;
    private $formFactory;
    private $userManager;
    private $tokenStorage;

    public function __construct(EventDispatcherInterface $eventDispatcher, FactoryInterface $formFactory, UserManagerInterface $userManager, TokenStorageInterface $tokenStorage)
    
        $this->eventDispatcher = $eventDispatcher;
        $this->formFactory     = $formFactory;
        $this->userManager     = $userManager;
        $this->tokenStorage    = $tokenStorage;
    

    public function registerAction(Request $request)
    
        dump('d1');
        $user = $this->userManager->createUser();
        $user->setEnabled(true);

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

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

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

        $form->handleRequest($request);

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

                $this->userManager->updateUser($user);

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

                $this->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(),
        ));
    


    public function confirmAction(Request $request, $token)
    
        dump('d');
        $userManager = $this->userManager;

        $user = $userManager->findUserByConfirmationToken($token);

        if (null === $user) 
            throw new NotFoundHttpException(sprintf('The user with confirmation token "%s" does not exist', $token));
        

        $user->setConfirmationToken(null);
        $user->setEnabled(true);

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

        $userManager->updateUser($user);

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

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

        return $response;
    

    public function confirmedAction(Request $request)
    
        $user = $this->getUser();
        if (!is_object($user) || !$user instanceof UserInterface) 
            throw new AccessDeniedException('This user does not have access to this section.');
        

        return $this->render('@FOSUser/Registration/confirmed.html.twig', array(
            'user' => $user,
            'targetUrl' => $this->getTargetUrlFromSession($request->getSession()),
        ));
    
    /**
     * @return string|null
     */
    private function getTargetUrlFromSession(SessionInterface $session)
    
        $key = sprintf('_security.%s.target_path', $this->tokenStorage->getToken()->getProviderKey());

        if ($session->has($key)) 
            return $session->get($key);
        

        return null;
    



Service.yml

# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
    locale: 'en'


services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/DependencyInjection,Entity,Migrations,Tests,Kernel.php'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']

    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones

    app.fos_overriding_routes:
        class: App\EventListener\FosOverridingRoutes
        arguments: ['@router']
        tags:
            -  name: kernel.event_subscriber 

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

routes.yaml

fos_user:
    resource: "@FOSUserBundle/Resources/config/routing/all.xml"
#    prefix: setting

fos_user_registration_register:
    resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
    defaults:  _controller: App\Controller\RegistrationController::registerAction
    #prefix: /register/

#
fos_user_registration_confirm:
    resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
    defaults:  _controller: App\Controller\RegistrationController::confirmAction 
    #path: /register/
    #prefix: /confirm/token
    prefix: /register/

【问题讨论】:

您是否已经尝试过使用 $request->get('token') 而不是直接将 $token 作为操作参数传递? 我尝试这样做。但无法使用主注册链接。 localhost:8000/register 获取主寄存器时同样的错误 收到此错误的完整 URL 是什么?您是否还尝试在您的 routes.yaml 中省略“defaults”条目并输入“path:/confirm/token”? localhost:8000/register/confirm/… 根据您的回答,我正在转储。但是获取此 URL 时出错 localhost:8000/register 我认为路由器问题? 那么您的确认 URL 是否适用于调整? 【参考方案1】:

尝试覆盖控制器操作时,请勿将资源条目与您自己的控制器条目结合起来

将路由改为:

fos_user_registration_register:  
    controller: App\Controller\RegistrationController::registerAction
    path: /register


fos_user_registration_confirm:
    controller:App\Controller\RegistrationController::confirmAction
    path: /register/confirm/token 

你也可以把路由放在你的控制器中,加上注解: https://symfony.com/doc/4.1/routing.html

【讨论】:

以上是关于无法解析 symfony 4.3 中覆盖 FOS 控制器的参数 $token的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 4/JMS/FOSUser:无法从 FOS\UserBundle 序列化数据

如何覆盖 FOS 用户捆绑表单标签

Symfony,FOS 用户:使用空输入密码编辑用户

FOS UserBundle 无法登录

Symfony 2 FOS 用户捆绑引导模式 AJAX 登录

Symfony2 - 安装了 FOS 用户包的自定义身份验证提供程序