如何在不使用bundle继承的情况下覆盖bundle模板和控制器(FOSUserBundle)

时间:2018-06-14 14:40:24

标签: symfony inheritance fosuserbundle symfony4

在我基于Symfony 2.8的项目中,我使用FOSUserBundle并使用捆绑继承使用自定义MyUserBundle对其进行扩展。

当尝试将FOSUserBundle从2.0.2更新为2.1.2时,我遇到了几个问题。

由于在Symfony 3.4中弃用了Bundle继承并在Symfony 4.0中完全删除了,因此我现在尝试在不使用bundle继承的情况下实现相同的结果。

我发现很多信息表明,只需将文件放在app/Resources/<BundleName>/...中即可覆盖捆绑资源。因此,FOSUserBundle

可以覆盖app/Resources/FOSUserBundle/views/<template.html.twig>个模板

虽然这会起作用,但它不会提供与bundle继承相同的结果。我可以在不同的项目中使用我继承的bundle,从而一遍又一遍地重用相同的代码。使用app/Resources/<BundleName>/...解决方案仅适用于当前项目。

问题1:如何覆盖自定义捆绑包中的模板(和其他资源),可以在不同的项目中使用,而不是在项目特定的app/Resources文件夹中使用?

问题2:如何覆盖不提供事件的控制器的行为?

目前我使用捆绑继承来覆盖confirmedAction以将用户发送到自定义设置页面而不是默认页面:

// Original FOSUserBundle code
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()),
    ));
}  


// MyUserBundle codes which should override the default behavior
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.');
    }

    // Send user to setup-page
    return $this->redirectToRoute('app_user_setup');
}

如何在不使用捆绑继承的情况下以相同的方式控制行为并将用户发送到设置页面而不是默认确认页面?

据我所知FOSUserBundle没有提供指定确认目标的选项。当然,我可以使用一些请求事件监听器拦截对已确认路由的请求并重新路由它。但这将是非常hacky。这是否是正确的解决方案,或者有更清洁的方法来实现这一目标吗?

1 个答案:

答案 0 :(得分:1)

从Symfony 4.0开始,在没有bundle继承的情况下覆盖bundle中的资源

关于控制器

路线!是现在实现它的方式,&#34;第一条路线找到胜利&#34;因此,请确保使用自定义控制器在原始路径之前定义相同的路径。 e.g:

<route id="fos_user_registration_confirmed" path="/confirmed" methods="GET">
    <default key="_controller">MyUserBundle\Controller\RegistrationController::confirmedAction</default>
</route>

然后,必须在MyUserBundle/Resources/config/routing/registration.xml路由文件之前导入路由文件FOSUserBundle。这样,您的自定义操作将被执行,而不是原始的fos_user.registration.controller:confirmedAction

关于模板

再次,&#34;找到的第一个模板赢了#34;因此,请确保在views Twig命名空间中的路径之前定义了捆绑FOSUser路径。您可以通过创建compiler pass

来实现这一目标
// MyUserBundle/DependencyInjection/Compiler/TwigPass.php

$path = dirname(__DIR__, 2).'/Resources/views';

$twigFilesystemLoaderDefinition = $container->findDefinition('twig.loader.native_filesystem');
$twigFilesystemLoaderDefinition->addMethodCall('prependPath', array($path, 'FOSUser'));

运行bin/console debug:twig检查Twig加载器路径,它应如下所示:

  @FOSUser               - vendor/acme/my-user-bundle/Resources/views                                               
                         - vendor/friendsofsymfony/user-bundle/Resources/views 

在此处,您可以在调用FOSUserBundle时覆盖Registration/confirmed.html.twig的任何模板,例如@FOSUser/Registration/confirmed.html.twig