【问题标题】:Symfony Localized Routes - Optional LocaleSymfony 本地化路由 - 可选语言环境
【发布时间】:2016-04-28 08:18:42
【问题描述】:

我希望以下网址提供适当的操作:

  • / - 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 注释即可实现此目的。这样,无论我是否传递 _locale 参数,我都可以使用 UrlGenerator 并指向相同的名称来生成本地化和非本地化路由。

【问题讨论】:

  • 您是否厌倦了使用github.com/schmittjoh/JMSI18nRoutingBundle?这似乎完全符合您的需要。
  • 谢谢,但我使用的是我自己的框架并且只使用了某些 Symfony 组件。我会看看他们是如何做的事情来尝试和得到一个想法。

标签: symfony routing


【解决方案1】:

虽然我的解决方案有点老套,但我已经设法让它工作了。首先,我从上面的路线中删除了路径的 {_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 类的集合。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多