Symfony2:使用前缀和登录路由

时间:2012-07-10 03:17:06

标签: php symfony

我正在设置允许以下路由的路由:

/client_a/dashboard/
/client_b/dashboard/

我在app/config/routing.yml中使用的前缀如下所示:

AcmeMainBundle:
    resource: "@AcmeMainBundle/Resources/config/routing.yml"
    prefix:   /{client}  

我遇到的问题是登录路由似乎遇到了前缀问题。以下是我导入主路由文件的/Resources/config/routing.yml中的条目:

acme_login:
    pattern: /login/
    defaults: {_controller: AcmeMainBundle:Main:login }

acme_login_check:
    pattern: /login_check
    # defaults: This is not required since the Firewall will handle this

acme_logout:
    pattern: /logout/
    # defaults: This is not required since the Firewall will handle this

登录页面显示正常,但在用户提交登录页面后,Symfony会抛出错误说明:

Unable to find the controller for path "/client_a/login_check". Maybe you forgot to add the matching route in your routing configuration?

在我看来,Symfony2在内部安全路由方面遇到困难,并在routing.yml中使用了前缀。

有什么方法可以解决这个问题?

注意:解决此问题的一种方法是更改​​routing.yml文件中的所有路由以包含{client}参数。唯一的问题是这是一个非常广泛的应用程序,具有大量的路由。除了登录期间的安全处理外,使用前缀可以创建奇迹。

谢谢,

JB

3 个答案:

答案 0 :(得分:1)

您需要的可能解决方案是:

文件:src / Acme / CoreBundle / Twig / PathExtension.php

<?php

namespace Acme\CoreBundle\Twig\Extension;

use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernel;

class PathExtension extends \Twig_Extension
{

    private $request;
    private $router;

    public function __construct(Router $router) {
        $this->router = $router;
    }

    public function onKernelRequest(GetResponseEvent $event) {
        if ($event->getRequestType() === HttpKernel::MASTER_REQUEST) {
            $this->request = $event->getRequest();
        }
    }

    public function getFunctions()
    {
        return array(
            'path_route' => new \Twig_Function_Method($this, 'getPath')
        );
    }

    public function getPath($name, $parameters = array())
    {
        $parameters = array_merge($parameters, [
            'client' => $this->request->get('client'),
        ]);

        return $this->router->generate($name, $parameters, false);
    }

    public function getName()
    {
        return 'twig_path_route_extension';
    }

}

配置为服务:

文件:src / Acme / CoreBundle / Resources / config / services.yml

services:
    twig.path_route_extension:
        class: Acme\CoreBundle\Twig\PathExtension
        tags:
            - { name: twig.extension }
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
        arguments: [@router]

设置路由选项:

文件:app / config / routing.yml

_acme_client:
    resource: "@AcmeCoreBundle/Resources/config/routing.yml"
    prefix:   /{client}/

然后你可以在模板和routing.yml中使用它,例如:

_acme_client_dashboard:
    path:     /dashboard
    defaults: { _controller: AcmeCoreBundle:System:dashboard }

然后,在您的模板中,您可以使用:

<a href="{{ path_route('_acme_client_dashboard') }}">
  Link to Dashboard.
</a>

参考文献:

Pass path parameters automatically

http://blog.viison.com/post/15619033835/symfony2-twig-extension-switch-locale-current-route

答案 1 :(得分:0)

我认为您可能需要在defaults: {_controller: AcmeMainBundle:Main:login }的路线上定义控制器。它在默认情况下不需要它们,因为防火墙在路由之前捕获它。但在这种情况下可能需要它来匹配前缀。

答案 2 :(得分:0)

经过相当多的研究和尝试不同的方面,此时在路由中使用动态前缀似乎没有好的解决方案。

问题似乎是安全包在路由发生之前执行其代码,因此来自前缀的路由属性在security.yml中不可用,而是相当静态的路径。这本身就是导致问题,因为Symfony然后抱怨缺少属性等等。

所以,答案是,结合安全实施,上述是不可能的,至少不是我发现的方式。