路由

编辑本页

警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 3.3,现已不再维护。

本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。

路由

对于任何严肃的web应用程序来说,漂亮的url都是绝对必须的。这意味着留下丑陋的urlindex . php ?article_id = 57比如/读/ intro-to-sy欧宝娱乐app下载地址mfony

拥有灵活性更为重要。如果您需要更改页面的URL/博客/欧宝app在哪里找新闻?您需要查找和更新多少链接才能做出更改?如果您正在使用Symfony的路欧宝娱乐app下载地址由器,更改很简单。

Symf欧宝娱乐app下载地址ony路由器允许您定义可映射到应用程序不同区域的创造性url。在本文结束时,您将能够:

  • 创建映射到控制器的复杂路由
  • 在模板和控制器中生成url
  • 从包(或其他任何地方)加载路由资源
  • 调试路由

路由的例子

一个路线是从URL路径到控制器的映射。例如,假设您想匹配任何URL/博客/我的帖子/博客/ all-about-s欧宝娱乐app下载地址ymfony然后把它发送给一个控制器,这个控制器可以查找并渲染那个博客条目。路线很简单:

  • 注释
  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/ / src / AppBundle /控制器/ BlogController.php名称空间AppBundle控制器使用欧宝娱乐app下载地址FrameworkBundle控制器控制器使用Sensio赞助FrameworkExtraBundle配置路线BlogController扩展控制器/** *匹配/blog **@Route("/blog", name="blog_list") */公共函数listAction()/ /……/** *匹配/博客/** *@Route("/blog/{slug}", name="blog_show") */公共函数showAction鼻涕虫// $slug将等于URL的动态部分//例如:at /blog/ ay-routing,那么$slug=' ay-routing'/ /……}}

多亏了这两条路线:

  • 如果用户转到/博客,则匹配第一个路由listAction ()执行;
  • 如果用户转到/博客/ *,则第二条路由匹配和showAction ()是执行。因为路由路径是/博客/{蛞蝓},一个美元蛞蝓变量传递给showAction ()匹配这个值。例如,如果用户转到/博客/ yay-routing,然后美元蛞蝓就等于yay-routing

每当你有{占位符}在路由路径中,该部分成为通配符:它匹配任何价值。你的控制器现在可以有一个论证叫做美元的占位符(通配符和参数名必须匹配)。

每条路由也有一个内部名称:blog_list而且blog_show.它们可以是任何东西(只要每个都是唯一的),还没有任何意义。稍后,您将使用它来生成url。

@Route上面的每个方法称为注释.如果您更愿意在YAML、XML或PHP中配置路由,那也没问题!

在这些格式中,_controller"defaults" value是一个特殊的键,它告诉Symfony当URL匹配此路由时应欧宝娱乐app下载地址该执行哪个控制器。的_controller字符串被称为逻辑名.它遵循指向特定PHP类和方法的模式,在本例中为AppBundle \控制器\ BlogController:: listAction而且AppBundle \控制器\ BlogController:: showAction方法。

这就是Symfony路由器的目标:将请求的URL欧宝娱乐app下载地址映射到控制器。在此过程中,您将学习各种技巧,使映射即使是最复杂的url也很容易。

添加{通配符}需求

想象一下blog_listroute将包含一个分页的博客文章列表,带有类似于/博客/ 2而且/博客/ 3第2和第3页。如果将路由路径更改为页面/博客/ {},你会遇到一个问题:

  • blog_list:页面/博客/ {}将匹配/博客/ *
  • blog_show:/博客/{蛞蝓}匹配/博客/ *

当两个路由匹配相同的URL时第一个加载的路由获胜。不幸的是,这意味着/博客/ yay-routing将匹配blog_list.没有好!

若要修复此问题,请添加要求这一{页面}通配符可以只有匹配数字(数字):

  • 注释
  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ / src / AppBundle /控制器/ BlogController.php名称空间AppBundle控制器使用欧宝娱乐app下载地址FrameworkBundle控制器控制器使用Sensio赞助FrameworkExtraBundle配置路线BlogController扩展控制器/ * * *@Route(“/博客/{页面}”,name = " blog_list "需求={"页面" = " \ d + "}) * /公共函数listAction页面/ /……/ * * *@Route("/blog/{slug}", name="blog_show") */公共函数showAction鼻涕虫/ /……}}

\ d +正则表达式是否匹配数字任何长度。现在:

URL 路线 参数
/博客/ 2 blog_list 美元的页面2
/博客/ yay-routing blog_show 美元蛞蝓yay-routing

要了解其他路由要求(如HTTP方法、主机名和动态表达式),请参见如何定义路由需求

给{占位符}一个默认值

在前面的示例中,blog_list有一条路径页面/博客/ {}.如果用户访问/博客/ 1,它会匹配。但是如果他们来访/博客,它会匹配。只要你加入a{占位符}到一个路线,它必须要有价值。

那么你怎么做blog_list当用户访问时再次匹配/博客?通过添加默认的值:

  • 注释
  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ / src / AppBundle /控制器/ BlogController.php名称空间AppBundle控制器使用欧宝娱乐app下载地址FrameworkBundle控制器控制器使用Sensio赞助FrameworkExtraBundle配置路线BlogController扩展控制器/ * * *@Route(“/博客/{页面}”,name = " blog_list "需求={"页面" = " \ d + "}) * /公共函数listAction页面1/ /……}}

现在,当用户访问/博客,blog_list路由将匹配美元的页面将默认为1

高级路由实例

记住这些,看看这个高级的例子:

  • 注释
  • YAML
  • XML
  • PHP
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ / src / AppBundle /控制器/ ArticleController.php/ /……ArticleController扩展控制器/ * * *@Route(* "/articles/{_locale}/{year}/{slug}。{_format}", * defaults={"_format": "html"}, * requirements={ * "_locale": "en|fr", * "_format": "html|rss", * "year": "\d+" * } * ) */公共函数showAction_locale一年鼻涕虫{}}

如您所见,只有当{_locale}URL的一部分是任意一个fr如果{一}是一个数字。这条路由还展示了如何在占位符之间使用点而不是斜线。与此路由匹配的url可能是这样的:

  • /文章/ en / 2010 /我的帖子
  • / / fr / 2010 / my-post.rss文章
  • / / en / 2013 / my-latest-post.html文章

这个例子也强调了特殊性_format路由参数。使用此参数时,匹配的值将成为请求格式请求对象。

请求格式最终用于设置内容类型的响应(例如ajson请求格式转换为内容类型application / json).它也可以在控制器中用于为的每个值呈现不同的模板_format.的_format参数是一种非常强大的以不同格式呈现相同内容的方法。

在3.欧宝娱乐app下载地址0之前的Symfony版本中,可以通过添加名为的查询参数覆盖请求格式_format(例如:/ foo / bar吗?_format=json).依赖这种行为不仅被认为是一种不好的做法,而且会使您的应用程序升级到Symfony 3变得复杂。欧宝娱乐app下载地址

请注意

有时你想让你的路由的某些部分全局可配置。欧宝娱乐app下载地址Symfony通过利用服务容器参数为您提供了一种方法。详情请参阅“如何在路由中使用服务容器参数".

谨慎

路由占位符名称不能以数字开头,也不能超过32个字符。

特殊路由参数

如您所见,每个路由参数或默认值最终都可以作为控制器方法中的参数使用。此外,还有四个特殊的参数:每个参数在应用程序中添加一个独特的功能:

_controller
如您所见,此参数用于确定路由匹配时执行哪个控制器。
_format
用于设置请求格式(阅读更多).
_fragment

用于设置片段标识符,以。开头的URL的可选的最后一部分字符,用于标识文档的一部分。

3.2

_fragment参数在Symfony 3.2中引入。欧宝娱乐app下载地址

_locale
用于设置请求的区域设置(阅读更多).
..指数::
单:路由;控制器单:控制器;字符串命名格式

控制器命名模式

如果使用YAML、XML或PHP路由配置,则每个路由必须有一个_controller参数,该参数指定当路由匹配时应该执行哪个控制器。该参数使用一个简单的字符串模式,称为逻辑控制器名称, Symfon欧宝娱乐app下载地址y将其映射到特定的PHP方法和类。该模式由三个部分组成,每个部分由冒号分隔:

控制器行动

例如,_controller的价值AppBundle:博客:显示意思是:

控制器类 方法名称
AppBundle BlogController showAction ()

控制器看起来是这样的:

12 3 4 5 6 7 8 9 10 11 12
/ / src / AppBundle /控制器/ BlogController.php名称空间AppBundle控制器使用欧宝娱乐app下载地址FrameworkBundle控制器控制器BlogController扩展控制器公共函数showAction鼻涕虫/ /……}}

注意,Symfony添加欧宝娱乐app下载地址了字符串控制器到类名(博客= >BlogController),行动到方法名(显示= >showAction ()).

你也可以使用它的全限定类名和方法来引用这个控制器:AppBundle \控制器\ BlogController:: showAction.但是如果您遵循一些简单的约定,逻辑名称将更加简洁,并允许更多的灵活性。

提示

将实现的操作引用为__invoke ()方法,你不必传递方法名,但可以只使用完全限定类名(例如。AppBundle \ \ BlogController控制器).

请注意

除了使用逻辑名或全限定类名之外,Symfony还支持第三种引用控制器的方式。欧宝娱乐app下载地址这种方法只使用一个冒号分隔符(例如。service_name: indexAction),并将控制器引用为服务(参见如何将控制器定义为服务).

加载路径

欧宝娱乐app下载地址Symfony加载应用程序的所有路由路由配置文件:应用程序/配置/ routing.yml.但是在这个文件中,你可以加载任何文件其他路由您需要的文件。事实上,默认情况下,Symfony从App欧宝娱乐app下载地址Bundle的注释路由配置中加载注释路由配置控制器/目录,这是Symfony看到注释路由的方式:欧宝娱乐app下载地址

  • YAML
  • XML
  • PHP
1 2 3 4
# app / config / routing.yml应用:资源:“@AppBundle /控制器/”类型:注释

有关加载路由的详细信息,包括如何为加载路由的路径添加前缀,请参见如何包括外部路由资源

生成的url

路由系统还应该用于生成url。实际上,路由是一个双向系统:将URL映射到控制器,并将路由映射回URL。

要生成URL,您需要指定路由的名称(例如:blog_show)和任何通配符(例如:Slug = my blog-post)用于该路由的路径。有了这些信息,任何URL都可以很容易地生成:

12 3 4 5 6 7 8 9 10 11 12 13
MainController扩展控制器公共函数showAction鼻涕虫/ /……/ / /博客/我的博客帖子url->generateUrl (“blog_show”数组“鼻涕虫”= >“我的博客帖子”));}}

请注意

generateUrl ()方法中定义的控制器类只是这段代码的快捷方式:

1 2 3 4
url->容器->get (“路由器”->生成(“blog_show”数组“鼻涕虫”= >“我的博客帖子”));

使用查询字符串生成url

生成()方法接受一个通配符值数组来生成URI。但是如果你传递了额外的参数,它们将作为查询字符串添加到URI中:

1 2 3 4 5
->get (“路由器”->生成(“博客”数组“页面”= >2“类别”= >S欧宝娱乐app下载地址ymfony的));/ / /博客/ 2 ?类别= Symfo欧宝娱乐app下载地址ny

从模板生成url

要在Twig内部生成url,请参阅模板文章:创建和使用模板.如果还需要用JavaScript生成url,请参见如何在JavaScript中生成路由url

生成绝对url

默认情况下,路由器将生成相对url(例如。/博客).从控制器,通过UrlGeneratorInterface: ABSOLUTE_URL的第三个参数generateUrl ()方法:

1 2 3 4
使用欧宝娱乐app下载地址组件路由发电机UrlGeneratorInterface->generateUrl (“blog_show”数组“鼻涕虫”= >“我的博客帖子”), UrlGeneratorInterface::ABSOLUTE_URL);/ / http://www.example.com/blog/my-blog-post

请注意

生成绝对URL时使用的主机将使用当前的请求对象。当从web上下文之外生成绝对url时(例如在控制台命令中),这是行不通的。看到如何从控制台生成url学习如何解决这个问题。

故障排除

下面是一些你在使用路由时可能会看到的常见错误:

控制器"AppBundle\Controller\BlogController::showAction()"要求你为"$slug"参数提供一个值。

当你的控制器方法有一个参数(例如。美元蛞蝓):

1 2 3 4
公共函数showAction鼻涕虫/ / . .

但是你的路线可以有一个{蛞蝓}通配符(例如,它是/博客/显示).添加一个{蛞蝓}到您的路线路径:/博客/显示/{蛞蝓}或者给参数一个默认值(即。$slug = null).

缺少一些必要的参数(“slug”)来为路由“blog_show”生成URL。

对象的URLblog_show但你是传递一个鼻涕虫值(这是必需的,因为它有一个{蛞蝓})在路由路径中的通配符。为了解决这个问题,传递一个鼻涕虫生成路由时的值:

1 2 3 4
->generateUrl (“blog_show”数组“鼻涕虫”= >“slug-value”));//或者,在Twig中/ /{{路径(blog_show,{“鼻涕虫”:“slug-value”})}}

翻译路线

欧宝娱乐app下载地址Symfony不支持根据用户语言定义不同内容的路由。在这些情况下,您可以为每个控制器定义多条路由,每种路由对应支持的语言;或者使用社区创建的任何包来实现此特性,例如欧宝下载链接JMSI18nRoutingBundle而且BeSimpleI18nRoutingBundle

总结

路由是一种将传入请求的URL映射到应调用以处理请求的控制器函数的系统。它既允许您指定漂亮的url,又使应用程序的功能与这些url分离。路由是一种双向机制,这意味着它也应该用于生成url。

继续前进!

路由,请检查!现在,揭开…的力量控制器

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。