使用友好URL的可选分页参数为符号路由添加尾随斜杠


Add trailing slashes to symfony routing with optional pagination parameter of friendly URL

我有以下路由配置:

# Resources/config/routing.yml
AcmeBundle_article:
    resource: "@AcmeBundle/Resources/config/routing/article.yml"
    prefix:   /article
# Resources/config/routing/article.yml
acme_article:
    path:     /{page}
    defaults: { _controller: AcmeBundle:Article:index, page: 1 }

每当我调用$this->redirect($this->generateUrl('acme_article')){{ path('acme_article') }}时,URL都没有尾部斜杠/,例如example.com/article。我希望它像

example.com/article/<=默认首页
example.com/article/1
example.com/article/2

当我在没有{page}参数的情况下更改路线时,如下

# Resources/config/routing/article.yml
acme_article:
    path:     /
    defaults: { _controller: AcmeBundle:Article:index }

然后,按照我的预期添加尾部斜线:

example.com/article/
example.com/article/?page=1
example.com/article/?page=2

然而,我想在路由中保留{page},只想在没有页面参数的情况下添加尾部斜杠。是否可以在Symfony 2中进行路由?

您可以这样做:

# Resources/config/routing/article.yml
acme_article:
    pattern: /{page}
    defaults: { _controller: AcmeBundle:Article:index, page: 1 }
    requirements:
        page: ".*"

在你的控制器中:

// ArticleController.php
public function indexAction($page)
{
    if (!$page) {
        $page = 1;
    }
}

现在您可以使用访问路线

/article   # page = 1
/article/  # page = 1
/article/2 # page = 2

编辑

要保留参数的类型提示,只需在方法中添加一个check即可。示例:

// Article:index
if ($page && intval($page) < 1) {
    return $this->redirect('/article/');
}

由于未设置page,因此保留了尾部斜杠。

编辑2

下面的解决方案似乎更清洁。

# Resources/config/routing/article.yml
acme_article:
    pattern: /{page}
    defaults: { _controller: AcmeBundle:Article:index, page: 1 }
    requirements:
        page: 'd*

此选项允许使用尾部斜线,并且page参数必须是一个数字(如果已设置)。

它可以解决您在URL中允许斜杠的问题,但如果您不在生成的URL末尾手动添加尾部斜杠,则不会自动重定向(我知道它不是很干净,但找不到其他选择:/)。

我一直在寻找一种使用路由配置来解决这个问题的方法,但我认为这是不可能的。然而,我通过一些调整使它发挥了作用。

(1)我在路由中添加了一个变量trailingSlash,默认值为/。我使用KnpPaginator进行分页。当对第一页进行分页时,默认值/是必需的,否则URL中不会附加尾部斜杠。

acme_article:
    path:     /{trailingSlash}{page}
    defaults: { _controller: AcmeBundle:Article:index, trailingSlash: /, page: 1 }
    requirements:
        trailingSlash : '/?'

(2)我在Article:index控制器中添加了一些参数处理。如果找不到尾部斜杠,则抛出一个错误。

public function indexAction($trailingSlash = null, $page = 1)
{
    $request = $this->container->get('request');
    // if there is $page, $trailingSlash will be empty
    if (($trailingSlash == '/' && $page >= 1) || !is_numeric($page)) {
        throw new NotFoundHttpException(sprintf('No route found for "%s"', $request->getPathInfo()));
    }
    // ...
    return $this->render('AcmeBundle:Article:index.html.twig', array(
        'articles'          => $articles,
        'pagination'        => $pagination,
        'totalArticles'     => $pagination->getTotalItemCount(),
        'trailingSlash'     => $trailingSlash
    ));
}

(3)我不得不在控制器和细枝中的每个URL生成中添加一个尾随斜杠。

// Controller
$this->redirect($this->generateUrl('acme_article').'/');
// Twig
{{ path('acme_article') }}/

(4)从SEO的角度来看,我强制在rel="canonical"中为page=1 添加尾部斜线

{% block canonical %}
    <!-- trailingSlash is / when page = 1 -->
    <!-- trailingSlash is empty when page > 1 -->
    <link rel="canonical" href="{{ url(app.request.get('_route'), app.request.get('_route_params')) }}{{ trailingSlash }}" />
{% endblock %}

它解决了这个问题,但我觉得这是一个变通办法。我们欢迎更好的解决方案。