如何定义路由条件
路由的requirements(条件),可以令特定的路由只匹配特定的条件(conditions)。最简单的例子,就是限制一个路由的{通配符}只匹配某些表达式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// src/AppBundle/Controller/BlogController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class BlogController extends Controller
{
/**
* @Route("/blog/{page}", name="blog_list", requirements={"page": "\d+"})
*/
public function listAction($page)
{
// ...
}
} |
|
# app/config/routing.yml
blog_list:
path: /blog/{page}
defaults: { _controller: AppBundle:Blog:list }
requirements:
page: '\d+' |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!-- app/config/routing.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="Http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="blog_list" path="/blog/{page}">
<default key="_controller">AppBundle:Blog:list</default>
<requirement key="page">\d+</requirement>
</route>
<!-- ... -->
</routes> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('blog_list', new Route('/blog/{page}', array(
'_controller' => 'AppBundle:Blog:list',
), array(
'page' => '\d+'
)));
// ...
return $collection; |
得益于\d+
条件(它可以是一个任意长度的数字),/blog/2
将匹配这个路由,但/blog/my-blog-post
则不匹配。
由于参数要求是正则表达式,每个条件的复杂程度和灵活性都完全由你控制。假定你的程序首页基于不同的URL可以使用两种不同的语言:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// src/AppBundle/Controller/MainController.php
// ...
class MainController extends Controller
{
/**
* @Route("/{_locale}", defaults={"_locale": "en"}, requirements={
* "_locale": "en|fr"
* })
*/
public function homepageAction($_locale)
{
}
} |
|
# app/config/routing.yml
homepage:
path: /{_locale}
defaults: { _controller: AppBundle:Main:homepage, _locale: en }
requirements:
_locale: en|fr |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- app/config/routing.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="homepage" path="/{_locale}">
<default key="_controller">AppBundle:Main:homepage</default>
<default key="_locale">en</default>
<requirement key="_locale">en|fr</requirement>
</route>
</routes> |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('homepage', new Route('/{_locale}', array(
'_controller' => 'AppBundle:Main:homepage',
'_locale' => 'en',
), array(
'_locale' => 'en|fr',
)));
return $collection; |
根据传入的请求,URL的{_locale}
部分要匹配正则表达式(en|fr)
。
Path/路径 |
Parameters/参数 |
/ |
{_locale} = "en"
|
/en |
{_locale} = "en"
|
/fr |
{_locale} = "fr"
|
/es |
won't match this route |
路由条件中也可以包含容器参数,这篇文章对此进行了解释。当你的程序正则非常复杂且多次使用时,这会非常好用。
添加HTTP方法的条件 ¶
除了URL,你还能对传入的请求的“方法(method)”进行匹配(如GET、HEAD、POST、PUT、DELETE)。假设你为你的博客创建了一个API,并且你有两个路由:一个用于显示主题(GET请求或者HEAD请求),一个用于更新主题(PUT请求),这可以通过以下路由配置来实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// src/AppBundle/Controller/MainController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
// ...
class BlogApiController extends Controller
{
/**
* @Route("/api/posts/{id}")
* @Method({"GET","HEAD"})
*/
public function showAction($id)
{
// ... return a json response with the post
}
/**
* @Route("/api/posts/{id}")
* @Method("PUT")
*/
public function editAction($id)
{
// ... edit a post
}
} |
|
# app/config/routing.yml
api_post_show:
path: /api/posts/{id}
defaults: { _controller: AppBundle:BlogApi:show }
methods: [GET, HEAD]
api_post_edit:
path: /api/posts/{id}
defaults: { _controller: AppBundle:BlogApi:edit }
methods: [PUT] |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!-- app/config/routing.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="api_post_show" path="/api/posts/{id}" methods="GET|HEAD">
<default key="_controller">AppBundle:BlogApi:show</default>
</route>
<route id="api_post_edit" path="/api/posts/{id}" methods="PUT">
<default key="_controller">AppBundle:BlogApi:edit</default>
</route>
</routes> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection = new RouteCollection();
$collection->add('api_post_show', new Route('/api/posts/{id}', array(
'_controller' => 'AppBundle:BlogApi:show',
), array(), array(), '', array(), array('GET', 'HEAD')));
$collection->add('api_post_edit', new Route('/api/posts/{id}', array(
'_controller' => 'AppBundle:BlogApi:edit',
), array(), array(), '', array(), array('PUT')));
return $collection; |
尽管事实上这两个路由有着相同的路径(/api/posts/{id}
),但第1个路由将只匹配GET请求或者HEAD请求,而第2个路由将只匹配PUT请求。这就意味着你可以通过同样的URL去显示和提交表单,却能调用控制器的两个不同的action。
如果没有methods
被指定,这个路由将匹配所有方法(methods)。
如果你使用HTML表而且HTTP methods不同于GET
和POST
,你需要包容一个_method
参数(parameter)来令HTTP方法无效化(fake)。参考如何改变表单的Action和Method以了解更多。
添加主机条件 ¶
你也可以匹配HTTP上的主机传入的请求。欲了解更多请求,请参阅 如何基于Host来匹配路由 。
利用表达式添加动态条件 ¶
对于极为复杂的条件,你应该使用动态的表达式以匹配请求中的任何 信息。参考如何通过条件来限制路由匹配。