漂亮的URL絕對是一個嚴肅的web應用程序必須作到的,這種方式使index.php?article_id=57這類的醜陋URL被隱藏,由更受歡迎的像 /read/intro-to-symfony 來替代。javascript
擁有靈活性更爲重要,若是你要改變一個頁面的URL,好比從/blog 到 /new 怎麼辦?
有多少連接須要你找出來並更新呢? 若是你使用Symfony的router,這種改變將變得很簡單。php
Symfony2 router讓你定義更具創造力的URL,你能夠map你的應用程序的不一樣區域。
建立複雜的路由並map到controllers並能夠在模板和controllers內部生成URLs
從bundles(或者其餘任何地方)加載路由資源
調試你的路由html
路由活動
一個路徑是一個從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格式:java
<!-- 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代碼格式:git
// 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。github
_controller參數是一個特定的鍵,它告訴Symfogy當一個URL匹配這個路徑時哪一個controller將要被執行。
_controller字符串被稱爲邏輯名。它的值會按照特定的模式來指定具體的PHP類和方法。web
// 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。json
路由:內部的祕密
當一個請求發送到應用程序時,它包含一個客戶端想要獲取資源的地址。這個地址叫作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。