Symfony本地化路由 - 可选区域设置

时间:2016-04-28 08:18:43

标签: symfony routing

我希望以下网址提供相应的操作:

  • / - indexAction
  • / fr - indexAction
  • / foo - detailsAction(slug = foo)
  • / fr / foo - detailsAction(slug = foo)

我添加了以下操作方法:

/**
 * @Route("/{_locale}", name="home", defaults={"_locale": ""}, requirements={"_locale": "fr|es"})
 */
public function indexAction() {
    ...
}

/**
 * @Route("/{_locale}/{slug}", name="details", defaults={"_locale": ""}, requirements={"_locale": "fr|es"})
 */
public function detailsAction($slug) {
    ...
}

如果我去/,/ fr和/ fr / foo,这可以正常工作。但是,当我去/ foo时,它找不到匹配的路线。如果有人能告诉我这是怎么回事,我会很感激。

请注意,理想情况下,我希望无需为特定操作方法添加多个@Route注释即可实现此目的。这样我可以使用UrlGenerator并指向相同的名称来生成本地化和非本地化路由,无论我是否传递_locale参数。

1 个答案:

答案 0 :(得分:0)

尽管我的解决方案有点笨拙,但我还是设法让它工作。首先,我删除了路径的{_locale}部分,上面路线的默认值和要求。

然后当我创建我的路线时,我说:

$routes = new RouteCollection();

// Load the routes
...

$routes->addPrefix('/{_locale}', ['_locale' => ''], ['_locale' => '|fr|es']);

这会自动将定位位(上面删除)添加到路径中,以便可以在一个位置轻松配置。我使用以下内容将RouteCollection更改为我自己的类型:

use Symfony\Component\Routing\RouteCollection as BaseRouteCollection;

class RouteCollection extends BaseRouteCollection {
    public function addPrefix($prefix, array $defaults = [], array $requirements = []) {
        foreach ($this->all() as $route) {
            $route->setPath($prefix . rtrim($route->getPath(), '/'));
            $route->addDefaults($defaults);
            $route->addRequirements($requirements);
        }
    }
}

这可确保本地化主页路由不以正斜杠结束,例如/ FR /.

最后,我必须使用以下内容覆盖Route类:

use ReflectionProperty;
use Symfony\Component\Routing\Route as BaseRoute;

class Route extends BaseRoute {
    public function compile() {
        // Call the parent method to get the compiled route
        $compiledRoute = parent::compile();

        // Override the regex property
        $property = new ReflectionProperty($compiledRoute, 'regex');
        $property->setAccessible(true);
        $property->setValue($compiledRoute, str_replace('^/', '^/?', $compiledRoute->getRegex()));

        return $compiledRoute;
    }
}

这是特别hacky但是可以节省你不必添加更多代码堆。它只是替换正则表达式,以便第一个正斜杠是可选的,允许/ foo url工作。注意:您必须确保您的RouteCollection是此类的集合,而不是Symfony Route类。

希望这有帮助。