使用友好URL的可选分页参数向symfony路由添加尾部斜杠

时间:2015-12-07 05:11:10

标签: php symfony routing

我有以下路由配置:

# 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') }}时,网址都不会跟踪斜杠/,例如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},只想在没有page参数时添加尾部斜杠。是否可以在Symfony 2路由中进行?

2 个答案:

答案 0 :(得分: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

修改

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

// 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 :(得分:1)

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

(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 %}

它修复了问题,但我觉得这是一个解决方法。欢迎提供更好的解决方案。