Symfony2学习笔记之系统路由详解
本文详细讲述了symfony2的系统路由。分享给大家供大家参考,具体如下:
漂亮的url绝对是一个严肃的web应用程序必须做到的,这种方式使index.php?article_id=57这类的丑陋url被隐藏,由更受欢迎的像 /read/intro-to-symfony 来替代。
拥有灵活性更为重要,如果你要改变一个页面的url,比如从/blog 到 /new 怎么办?
有多少链接需要你找出来并更新呢? 如果你使用symfony的router,这种改变将变得很简单。
symfony2 router让你定义更具创造力的url,你可以map你的应用程序的不同区域。
创建复杂的路由并map到controllers并可以在模板和controllers内部生成urls
从bundles(或者其他任何地方)加载路由资源
调试你的路由
路由活动
一个路径是一个从url 模式到一个controller的绑定。
比如假设你想匹配任何像 /blog/my-post 或者 /blog/all-about-symfony的路径并把它们发送到一个controller在那里可以查找并渲染blog实体。
该路径很简单:
yaml格式:
# app/config/routing.yml blog_show: pattern: /blog/{slug} defaults: {_controller: acmeblogbundle:blog:show }
xml格式:
<!-- 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_show" pattern="/blog/{slug}"> <default key="_controller">acmeblogbundle:blog:show</default> </route> </routes>
php代码格式:
// app/config/routing.php use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog_show', new route('/blog/{slug}', array( '_controller' => 'acmeblogbundle:blog:show', )));
blog_show路径定义了一个url模式,它像/blog/* 这里的通配符被命名为slug。对于url/blog/my-blog-post,slug变量会得到值 my-blog-post。
_controller参数是一个特定的键,它告诉symfogy当一个url匹配这个路径时哪个controller将要被执行。
_controller字符串被称为逻辑名。它的值会按照特定的模式来指定具体的php类和方法。
// src/acme/blogbundle/controller/blogcontroller.php namespace acme\blogbundle\controller; use symfony\bundle\frameworkbundle\controller\controller; class blogcontroller extends controller { public function showaction($slug) { $blog = // use the $slug variable to query the database return $this->render('acmeblogbundle:blog:show.html.twig', array( 'blog' => $blog, )); } }
现在当你再访问/blog/my-post 时,showaction controller将被执行并且$slug变量的值为my-post
symfogy2 的路由器目标:映射一个请求的url到controller。
路由:内部的秘密
当一个请求发送到应用程序时,它包含一个客户端想要获取资源的地址。这个地址叫做url或者uri。可能是/contact,/blog/read-me或者其它样式。
get /blog/my-blog-post
symfony2 路由系统的目标是解析这些url并决定哪个controller应该被执行来回复该请求。
整个路由过程可以分为:
1.请求被symfony2的前端控制器(app.php)处理。
2.symfony2核心(kernel)要求路由器检查请求。
3.路由器匹配接收到的url到一个特定的路径并返回有关信息,包括应该被执行的controller。
4.symfony2核心执行该controller,该controller最终会返回一个response对象。
路由器层就是一个把接收到的url转换为要执行的特定controller的工具。
创建路由
symfony会从一个单独的路由配置文件中加载你应用程序的所有路由。该文件通常为 app/config/routing.yml。 它可以被配置成包括xml或者php文件等文件。
yaml格式:
# app/config/config.yml framework: # ... router: { resource: "%kernel.root_dir%/config/routing.yml" }
xml格式:
<!-- app/config/config.xml --> <framework:config ...> <!-- ... --> <framework:router resource="%kernel.root_dir%/config/routing.xml" /> </framework:config>
php代码格式:
// app/config/config.php $container->loadfromextension('framework', array( // ... 'router' => array('resource' => '%kernel.root_dir%/config/routing.php'), ));
基础路由配置
定义一个路由很简单,通常一个应用程序拥有很多路由。一个基础路由是由两部分组成:pattern部分和defaults数组部分。
比如:
yaml格式:
_welcome: pattern: / defaults: { _controller: acmedemobundle:main:homepage }
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="_welcome" pattern="/"> <default key="_controller">acmedemobundle:main:homepage</default> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('_welcome', new route('/', array( '_controller' => 'acmedemobundle:main:homepage', ))); return $collection;
该路由匹配首页(/)并映射到acmedemobundle:main:homepage controller。_controller字符串被symfony2翻译成一个相应的php函数并被执行。
带占位符路由
当然,路由系统支持更多有趣的路由。许多路由会包含一个或者多个被命名的通配符占位符。
yaml格式:
blog_show: pattern: /blog/{slug} defaults: { _controller: acmeblogbundle:blog:show }
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_show" pattern="/blog/{slug}"> <default key="_controller">acmeblogbundle:blog:show</default> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog_show', new route('/blog/{slug}', array( '_controller' => 'acmeblogbundle:blog:show', ))); return $collection;
该模式将匹配任何类似/blog/*形式的url。匹配占位符{slug}的值将会在controller中被使用。换句话说,如果url是/blog/hello-world,则$slug变量值是hello-world, 该值将能在controller中被使用。该模式不会匹配像/blog, 因为默认情况下所有的占位符都是必须的。 当然可以通过在defaults数组中给这些占位符赋来改变它。
必需和可选占位符
我们来添加一个新的路由,显示所有可用的blog列表。
yaml格式:
blog: pattern: /blog defaults: { _controller: acmeblogbundle:blog:index }
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" pattern="/blog"> <default key="_controller">acmeblogbundle:blog:index</default> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog', new route('/blog', array( '_controller' => 'acmeblogbundle:blog:index', ))); return $collection;
到目前为止,我们的路由都是非常简单的路由模式。它们包含的非占位符将会被精确匹配。
如果你想该路由能够支持分页,比如让/blog/2 显示第二页的blog,那就需要为之前的路由添加一个新的{page}占位符。
yaml格式:
blog: pattern: /blog/{page} defaults: { _controller: acmeblogbundle:blog:index }
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" pattern="/blog/{page}"> <default key="_controller">acmeblogbundle:blog:index</default> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog', new route('/blog/{page}', array( '_controller' => 'acmeblogbundle:blog:index', ))); return $collection;
跟之前的{slug}占位符一样{page}占位符将会在你的controller内部可用,它的值可以用于表示要显示的blog值的页码。但是要清楚,因为占位符默认情况下都是必需的,该路由也将不再匹配之前的/blog url,这时候你如果还像看第一页的话,就必须通过/blog/1 url来访问了。要解决该问题,可以在该路由的defaults数组中指定{page}的默认值。
yaml格式:
blog: pattern: /blog/{page} defaults: { _controller: acmeblogbundle:blog:index, page: 1 }
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" pattern="/blog/{page}"> <default key="_controller">acmeblogbundle:blog:index</default> <default key="page">1</default> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog', new route('/blog/{page}', array( '_controller' => 'acmeblogbundle:blog:index', 'page' => 1, ))); return $collection;
通过添加page到defaults键, {page}占位符就不再是必需的。这时候 /blog将会被匹配并且page参数被设置为1,url /blog/2 也会被匹配。
添加要求约束
看看下面这些路由:
yaml格式:
blog: pattern: /blog/{page} defaults: { _controller: acmeblogbundle:blog:index, page: 1 } blog_show: pattern: /blog/{slug} defaults: { _controller: acmeblogbundle:blog:show }
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" pattern="/blog/{page}"> <default key="_controller">acmeblogbundle:blog:index</default> <default key="page">1</default> </route> <route id="blog_show" pattern="/blog/{slug}"> <default key="_controller">acmeblogbundle:blog:show</default> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog', new route('/blog/{page}', array( '_controller' => 'acmeblogbundle:blog:index', 'page' => 1, ))); $collection->add('blog_show', new route('/blog/{show}', array( '_controller' => 'acmeblogbundle:blog:show', ))); return $collection;
你发现问题了吗?注意这两个路由都能匹配像/blog/* 类型的url。symfony只会选择第一个与之匹配的路由。
换句话说,blog_show将永远不会被像/blog/* 类型的url匹配。而像 /blog/my-blog-post这样的url也会被blog路由匹配,并且page变量会获得my-blog-post这样的值。
这肯定不可以,那么怎么办呢?答案是给路由添加约束要求requirements。
在blog路由中占位符{page}理想状态下只匹配整数值。幸运的是正则表达可以很容易的满足这一要求。
yaml格式:
blog: pattern: /blog/{page} defaults: { _controller: acmeblogbundle:blog:index, page: 1 } requirements: page: \d+
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" pattern="/blog/{page}"> <default key="_controller">acmeblogbundle:blog:index</default> <default key="page">1</default> <requirement key="page">\d+</requirement> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('blog', new route('/blog/{page}', array( '_controller' => 'acmeblogbundle:blog:index', 'page' => 1, ), array( 'page' => '\d+', ))); return $collection;
这里 \d+ 约束是一个正则表达式,它指定了{page}只接受整数。这样像/blog/my-blog-post就不再被匹配了。这时候,它才会被blog_show路由匹配。因为参数的约束都是正则表达式,所以其复杂程度和灵活性都有你来决定了。
假设home页使用两种语言则可以这样配置路由:
yaml格式:
homepage: pattern: /{culture} defaults: { _controller: acmedemobundle:main:homepage, culture: en } requirements: culture: en|fr
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" pattern="/{culture}"> <default key="_controller">acmedemobundle:main:homepage</default> <default key="culture">en</default> <requirement key="culture">en|fr</requirement> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('homepage', new route('/{culture}', array( '_controller' => 'acmedemobundle:main:homepage', 'culture' => 'en', ), array( 'culture' => 'en|fr', ))); return $collection;
添加http 方法约束
除了url,你还可以匹配请求的方法(get,head,post,put,delete等)。假设你有一个联系表单有两个controller,一个用于显示表单(使用get请求)一个用于处理提交的表单(post请求)。它的配置如下:
yaml格式:
contact: pattern: /contact defaults: { _controller: acmedemobundle:main:contact } requirements: _method: get contact_process: pattern: /contact defaults: { _controller: acmedemobundle:main:contactprocess } requirements: _method: post
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="contact" pattern="/contact"> <default key="_controller">acmedemobundle:main:contact</default> <requirement key="_method">get</requirement> </route> <route id="contact_process" pattern="/contact"> <default key="_controller">acmedemobundle:main:contactprocess</default> <requirement key="_method">post</requirement> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('contact', new route('/contact', array( '_controller' => 'acmedemobundle:main:contact', ), array( '_method' => 'get', ))); $collection->add('contact_process', new route('/contact', array( '_controller' => 'acmedemobundle:main:contactprocess', ), array( '_method' => 'post', ))); return $collection;
尽管这两个路由拥有同一个url模式定义(/contact),但是第一个路由只会匹配get请求,而第二个只会匹配post请求。这就意味着你可以通过同一个url来显示表单并提交表单,而用不同的controller对他们进行处理。如果没有指定_method约束,那么该路由会匹配所有请求方法。跟其它约束一样,_method约束也接受正则表达式,如果只想匹配get或者post那么你可以用get|post
高级路由例子:
symfony2中具备一切让你创建任何形式路由的条件。
yaml格式:
article_show: pattern: /articles/{culture}/{year}/{title}.{_format} defaults: { _controller: acmedemobundle:article:show, _format: html } requirements: culture: en|fr _format: html|rss year: \d+
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="article_show" pattern="/articles/{culture}/{year}/{title}.{_format}"> <default key="_controller">acmedemobundle:article:show</default> <default key="_format">html</default> <requirement key="culture">en|fr</requirement> <requirement key="_format">html|rss</requirement> <requirement key="year">\d+</requirement> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('homepage', new route('/articles/{culture}/{year}/{title}.{_format}', array( '_controller' => 'acmedemobundle:article:show', '_format' => 'html', ), array( 'culture' => 'en|fr', '_format' => 'html|rss', 'year' => '\d+', ))); return $collection;
上面的路由,在匹配时只会匹配{culture}部分值为en或者fr并且{year}的值为数字的url。该路由还告诉我们,可以用在占位符之间使用区间代替斜线。
它能够匹配如下url:
/articles/en/2010/my-post
/articles/fr/2010/my-post.rss
这其中有个特殊的路由参数 _format,在使用该参数时,其值变为请求格式。这种请求格式相当于respose对象的content-type,比如json请求格式会翻译成一个content-type为application/json.该参数可以用于在controller中为每个_format渲染一个不同的模板。它是一个很强的方式来渲染同一个内容到不同的格式。
特殊的路由参数:
正如你所看到的,每一个路由参数或者默认值最终都是作为一个controller方法输入参数被使用。另外,有三个参数比较特别,它们每一个都在你的应用程序中增加一个唯一功能。
_controller: 这个参数决定了当路由匹配时,哪个controller被执行。
_format: 用于设置请求格式。
_locale: 用于在session上设置本地化。
controller的命名模式:
每一个路由必须有一个_controller参数,它决定了当路由匹配时哪个controller应该被执行。该参数使用单一的字符串模式,被称为logical controller name。
通过它symfony可以映射到一个特定的php方法和类。该模式有三部分,每一部分用冒号分割开:
bundle:controller:action
比如_controller 的值为 acmeblogbundle:blog:show 意思是acmeblogbundle bundle中blogcontroller类里面的showaction方法。
// src/acme/blogbundle/controller/blogcontroller.php namespace acme\blogbundle\controller; use symfony\bundle\frameworkbundle\controller\controller; class blogcontroller extends controller { public function showaction($slug) { // ... } }
symfony会自动把它们的添加相应的后缀,blog=>blogcontroller, show => showaction。
你也可以使用它的完全限定名和方法来给_controller赋值,acme\blogbundle\controller\blogcontroller::showaction 但一般为了简洁灵活而是用逻辑名称。另外除了上面两种形式外,symfony还支持第三种方式只有一个冒号分割符,如service_name:indexaction来为_controller赋一个作为服务使用的controller。
路由参数和控制器参数
路由参数非常重要,因为每一个路由参数都会转变成一个控制器参数被在方法中使用。
public function showaction($slug) { // ... }
事实上,全部的defaults集合和表单的参数值合并到一个单独的数组中。这个数组中的每个键都会成为controller方法的参数。换句话说,你的controller方法的每一个参数,symfony都会从路由参数中查找并把找到的值赋给给参数。上面例子中的变量 $culture, $year,$title,$_format,$_controller 都会作为showaction()方法的参数。因为占位符和defaults集合被合并到一起,即使$_controller变量也是一样。你也可以使用一个特殊的变量$_route 来指定路由的名称。
包括外部路由资源
所有的路由资源的都是通过一个单一的配置文件导入的。通常是app/config/routing.yml。当然你可能想从别处导入路由资源,比如你定义的bundle中的路由资源,你可以这样导入:
yaml格式:
# app/config/routing.yml acme_hello: resource: "@acmehellobundle/resources/config/routing.yml"
xml格式:
<!-- 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"> <import resource="@acmehellobundle/resources/config/routing.xml" /> </routes>
php代码格式:
// app/config/routing.php use symfony\component\routing\routecollection; $collection = new routecollection(); $collection->addcollection($loader->import("@acmehellobundle/resources/config/routing.php")); return $collection;
在使用yaml导入资源时,键(比如acme_hello)是没有意义的,只是用来保证该资源唯一不被其它行覆盖。使用resources key加载给定的路由资源。在这个示例中资源是一个全路径文件,@acmehellobundle是简写语法,它会被指向bundle路径。被导入的文件内容如下:
yaml格式:
# src/acme/hellobundle/resources/config/routing.yml acme_hello: pattern: /hello/{name} defaults: { _controller: acmehellobundle:hello:index }
xml格式:
<!-- src/acme/hellobundle/resources/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="acme_hello" pattern="/hello/{name}"> <default key="_controller">acmehellobundle:hello:index</default> </route> </routes>
php代码格式:
// src/acme/hellobundle/resources/config/routing.php use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('acme_hello', new route('/hello/{name}', array( '_controller' => 'acmehellobundle:hello:index', ))); return $collection;
这个文件中的路由会被解析并跟主要的路由文件内容一起被加载。
给导入的路由资源添加前缀
你可以为导入的路由资源选择一个前缀,比如说假设你想acme_hello路由有一个这样的 匹配模式:/admin/hello/{name} 而不是直接的 /hello/{name}
那么你在导入它的时候可以为其指定prefix。
yaml格式:
# app/config/routing.yml acme_hello: resource: "@acmehellobundle/resources/config/routing.yml" prefix: /admin
xml格式:
<!-- 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"> <import resource="@acmehellobundle/resources/config/routing.xml" prefix="/admin" /> </routes>
php代码格式:
// app/config/routing.php use symfony\component\routing\routecollection; $collection = new routecollection(); $collection->addcollection($loader->import("@acmehellobundle/resources/config/routing.php"), '/admin'); return $collection;
当该外部路由资源加载的时候字符串 /admin 将被插入到匹配模式的前面。
可视化并调试路由
当你添加和个性化路由时,能够看到它并能获取一些细节信息将是非常有用的。一个好的查看你应用程序的路由的方法是通过router:debug 命令行工具。
在你项目目录下执行如下命令:
$ php app/console router:debug
将会输出你应用程序的所有路由。你也可以在该命令后面添加某个路由的名字来获取单个路由信息
$ php app/console router:debug article_show
生成url
一个路由系统应该也能用来生成url。事实上,路由系统是一个双向的系统,映射url到controller+parameters 和 回对应到 一个url。可以使用match()和generate()方法来操作。比如:
$params = $router->match('/blog/my-blog-post'); // array('slug' => 'my-blog-post', '_controller' => 'acmeblogbundle:blog:show') $uri = $router->generate('blog_show', array('slug' => 'my-blog-post')); // /blog/my-blog-post
要生成一个url,你需要指定路由的名称(比如 blog_show)和任意的通配符(比如:slug=my-blog-post)作为参数。通过这些信息,可以生成任意的url。
class maincontroller extends controller { public function showaction($slug) { // ... $url = $this->get('router')->generate('blog_show', array('slug' => 'my-blog-post')); } }
那么如何从模板内部来生成url呢?如果你的应用程序前端使用了ajax请求,你也许想能够基于你的路由配置在javascript中生成url,通过使用
fosjsroutingbundle(https://github.com/friendsofsymfony/fosjsroutingbundle) 你可以做到:
var url = routing.generate('blog_show', { "slug": 'my-blog-post'});
生成绝对路径的url
默认的情况下,路由器生成相对路径的url(比如 /blog).要生成一个绝对路径的url,只需要传入一个true到generate方法作为第三个参数值即可。
$router->generate('blog_show', array('slug' => 'my-blog-post'), true); // http://www.example.com/blog/my-blog-post
当生成一个绝对路径url时主机是当前请求对象的主机,这个是基于php提供的服务器信息自动决定的。当你需要为运行子命令行的脚本生成一个绝对url时,你需要在request对象上手动设置期望的主机头。
$request->headers->set('host', 'www.example.com');
生成带有查询字符串的url
generate()带有一个数组通配符值来生成uri。 但是如果你传入额外的值,它将被添加到uri作为查询字符串:
$router->generate('blog', array('page' => 2, 'category' => 'symfony')); // /blog/2?category=symfony
从模板中生成url
最常用到生成url的地方是从模板中链接两个页面时,这来需要使用一个模板帮助函数:
twig格式:
<a href="{{ path('blog_show', { 'slug': 'my-blog-post' }) }}"> read this blog post. </a>
php格式:
<a href="<?php echo $view['router']->generate('blog_show', array('slug' => 'my-blog-post')) ?>"> read this blog post. </a>
也可以生成绝对路径:
twig格式:
<a href="{{ url('blog_show', { 'slug': 'my-blog-post' }) }}"> read this blog post. </a>
php格式:
<a href="<?php echo $view['router']->generate('blog_show', array('slug' => 'my-blog-post'), true) ?>"> read this blog post. </a>
强制路由使用https或者http
有时候为了安全起见,你需要你的站点必须使用https协议访问。这时候路由组件可以通过_scheme 约束来强迫uri方案。比如:
yaml格式:
secure: pattern: /secure defaults: { _controller: acmedemobundle:main:secure } requirements: _scheme: https
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="secure" pattern="/secure"> <default key="_controller">acmedemobundle:main:secure</default> <requirement key="_scheme">https</requirement> </route> </routes>
php代码格式:
use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('secure', new route('/secure', array( '_controller' => 'acmedemobundle:main:secure', ), array( '_scheme' => 'https', ))); return $collection;
上面的路由定义就是强迫secure路由使用https协议访问。
反之,当生成secure 的url的时候,路由系统会根据当前的访问协议方案生成相应的访问协议。比如当前是http,则会自动生成https访问;如果是https访问,那么就也会相应的生成https访问。
# 如果方案是 https {{ path('secure') }} # 生成 /secure # 如果方案是 http {{ path('secure') }} # 生成 https://example.com/secure
当然你也可以通过设置_scheme为http,来强制使用http访问协议。除了上面说的强迫使用https协议访问的设置方法外,还有一种用于站点区域设置
使用requires_channel 比如你想让你站点中/admin 下面的所有路由都必须使用https协议访问,或者你的安全路由定义在第三方bundle时使用。
总结:
路由系统是一个为将接收的请求url映射到被调用来处理该请求的controller函数的系统。它既能够让你生成漂亮的url同时又能保持你的应用程序功能跟这些url解耦。路由系统是双向机制的,也就是说它们也可以用来生成url。
希望本文所述对大家基于symfony框架的php程序设计有所帮助。