Symfony2學(xué)習(xí)筆記之系統(tǒng)路由詳解
本文詳細(xì)講述了Symfony2的系統(tǒng)路由。分享給大家供大家參考,具體如下:
漂亮的URL絕對(duì)是一個(gè)嚴(yán)肅的web應(yīng)用程序必須做到的,這種方式使index.php?article_id=57這類(lèi)的丑陋URL被隱藏,由更受歡迎的像 /read/intro-to-symfony 來(lái)替代。
擁有靈活性更為重要,如果你要改變一個(gè)頁(yè)面的URL,比如從/blog 到 /new 怎么辦?
有多少鏈接需要你找出來(lái)并更新呢? 如果你使用Symfony的router,這種改變將變得很簡(jiǎn)單。
Symfony2 router讓你定義更具創(chuàng)造力的URL,你可以map你的應(yīng)用程序的不同區(qū)域。
創(chuàng)建復(fù)雜的路由并map到controllers并可以在模板和controllers內(nèi)部生成URLs
從bundles(或者其他任何地方)加載路由資源
調(diào)試你的路由
路由活動(dòng)
一個(gè)路徑是一個(gè)從URL 模式到一個(gè)controller的綁定。
比如假設(shè)你想匹配任何像 /blog/my-post 或者 /blog/all-about-symfony的路徑并把它們發(fā)送到一個(gè)controller在那里可以查找并渲染blog實(shí)體。
該路徑很簡(jiǎn)單:
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路徑定義了一個(gè)URL模式,它像/blog/* 這里的通配符被命名為slug。對(duì)于URL/blog/my-blog-post,slug變量會(huì)得到值 my-blog-post。
_controller參數(shù)是一個(gè)特定的鍵,它告訴Symfogy當(dāng)一個(gè)URL匹配這個(gè)路徑時(shí)哪個(gè)controller將要被執(zhí)行。
_controller字符串被稱(chēng)為邏輯名。它的值會(huì)按照特定的模式來(lái)指定具體的PHP類(lèi)和方法。
// 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, )); } }
現(xiàn)在當(dāng)你再訪(fǎng)問(wèn)/blog/my-post 時(shí),showAction controller將被執(zhí)行并且$slug變量的值為my-post
Symfogy2 的路由器目標(biāo):映射一個(gè)請(qǐng)求的URL到controller。
路由:內(nèi)部的秘密
當(dāng)一個(gè)請(qǐng)求發(fā)送到應(yīng)用程序時(shí),它包含一個(gè)客戶(hù)端想要獲取資源的地址。這個(gè)地址叫做URL或者URI??赡苁?contact,/blog/read-me或者其它樣式。
GET /blog/my-blog-post
Symfony2 路由系統(tǒng)的目標(biāo)是解析這些URL并決定哪個(gè)controller應(yīng)該被執(zhí)行來(lái)回復(fù)該請(qǐng)求。
整個(gè)路由過(guò)程可以分為:
1.請(qǐng)求被Symfony2的前端控制器(app.php)處理。
2.Symfony2核心(kernel)要求路由器檢查請(qǐng)求。
3.路由器匹配接收到的URL到一個(gè)特定的路徑并返回有關(guān)信息,包括應(yīng)該被執(zhí)行的controller。
4.Symfony2核心執(zhí)行該controller,該controller最終會(huì)返回一個(gè)Response對(duì)象。
路由器層就是一個(gè)把接收到的URL轉(zhuǎn)換為要執(zhí)行的特定controller的工具。
創(chuàng)建路由
Symfony會(huì)從一個(gè)單獨(dú)的路由配置文件中加載你應(yīng)用程序的所有路由。該文件通常為 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'), ));
基礎(chǔ)路由配置
定義一個(gè)路由很簡(jiǎn)單,通常一個(gè)應(yīng)用程序擁有很多路由。一個(gè)基礎(chǔ)路由是由兩部分組成:pattern部分和defaults數(shù)組部分。
比如:
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;
該路由匹配首頁(yè)(/)并映射到AcmeDemoBundle:Main:homepage controller。_controller字符串被Symfony2翻譯成一個(gè)相應(yīng)的PHP函數(shù)并被執(zhí)行。
帶占位符路由
當(dāng)然,路由系統(tǒng)支持更多有趣的路由。許多路由會(huì)包含一個(gè)或者多個(gè)被命名的通配符占位符。
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;
該模式將匹配任何類(lèi)似/blog/*形式的URL。匹配占位符{slug}的值將會(huì)在controller中被使用。換句話(huà)說(shuō),如果URL是/blog/hello-world,則$slug變量值是hello-world, 該值將能在controller中被使用。該模式不會(huì)匹配像/blog, 因?yàn)槟J(rèn)情況下所有的占位符都是必須的。 當(dāng)然可以通過(guò)在defaults數(shù)組中給這些占位符賦來(lái)改變它。
必需和可選占位符
我們來(lái)添加一個(gè)新的路由,顯示所有可用的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;
到目前為止,我們的路由都是非常簡(jiǎn)單的路由模式。它們包含的非占位符將會(huì)被精確匹配。
如果你想該路由能夠支持分頁(yè),比如讓/blog/2 顯示第二頁(yè)的blog,那就需要為之前的路由添加一個(gè)新的{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}占位符將會(huì)在你的controller內(nèi)部可用,它的值可以用于表示要顯示的blog值的頁(yè)碼。但是要清楚,因?yàn)檎嘉环J(rèn)情況下都是必需的,該路由也將不再匹配之前的/blog URL,這時(shí)候你如果還像看第一頁(yè)的話(huà),就必須通過(guò)/blog/1 URL來(lái)訪(fǎng)問(wèn)了。要解決該問(wèn)題,可以在該路由的defaults數(shù)組中指定{page}的默認(rèn)值。
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;
通過(guò)添加page到defaults鍵, {page}占位符就不再是必需的。這時(shí)候 /blog將會(huì)被匹配并且page參數(shù)被設(shè)置為1,URL /blog/2 也會(huì)被匹配。
添加要求約束
看看下面這些路由:
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;
你發(fā)現(xiàn)問(wèn)題了嗎?注意這兩個(gè)路由都能匹配像/blog/* 類(lèi)型的URL。Symfony只會(huì)選擇第一個(gè)與之匹配的路由。
換句話(huà)說(shuō),blog_show將永遠(yuǎn)不會(huì)被像/blog/* 類(lèi)型的URL匹配。而像 /blog/my-blog-post這樣的URL也會(huì)被blog路由匹配,并且page變量會(huì)獲得my-blog-post這樣的值。
這肯定不可以,那么怎么辦呢?答案是給路由添加約束要求requirements。
在blog路由中占位符{page}理想狀態(tài)下只匹配整數(shù)值。幸運(yùn)的是正則表達(dá)可以很容易的滿(mǎn)足這一要求。
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+ 約束是一個(gè)正則表達(dá)式,它指定了{(lán)page}只接受整數(shù)。這樣像/blog/my-blog-post就不再被匹配了。這時(shí)候,它才會(huì)被blog_show路由匹配。因?yàn)閰?shù)的約束都是正則表達(dá)式,所以其復(fù)雜程度和靈活性都有你來(lái)決定了。
假設(shè)home頁(yè)使用兩種語(yǔ)言則可以這樣配置路由:
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,你還可以匹配請(qǐng)求的方法(GET,HEAD,POST,PUT,DELETE等)。假設(shè)你有一個(gè)聯(lián)系表單有兩個(gè)controller,一個(gè)用于顯示表單(使用GET請(qǐng)求)一個(gè)用于處理提交的表單(POST請(qǐng)求)。它的配置如下:
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;
盡管這兩個(gè)路由擁有同一個(gè)URL模式定義(/contact),但是第一個(gè)路由只會(huì)匹配GET請(qǐng)求,而第二個(gè)只會(huì)匹配POST請(qǐng)求。這就意味著你可以通過(guò)同一個(gè)URL來(lái)顯示表單并提交表單,而用不同的controller對(duì)他們進(jìn)行處理。如果沒(méi)有指定_method約束,那么該路由會(huì)匹配所有請(qǐng)求方法。跟其它約束一樣,_method約束也接受正則表達(dá)式,如果只想匹配GET或者POST那么你可以用GET|POST
高級(jí)路由例子:
Symfony2中具備一切讓你創(chuàng)建任何形式路由的條件。
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;
上面的路由,在匹配時(shí)只會(huì)匹配{culture}部分值為en或者fr并且{year}的值為數(shù)字的URL。該路由還告訴我們,可以用在占位符之間使用區(qū)間代替斜線(xiàn)。
它能夠匹配如下URL:
/articles/en/2010/my-post
/articles/fr/2010/my-post.rss
這其中有個(gè)特殊的路由參數(shù) _format,在使用該參數(shù)時(shí),其值變?yōu)檎?qǐng)求格式。這種請(qǐng)求格式相當(dāng)于Respose對(duì)象的Content-Type,比如json請(qǐng)求格式會(huì)翻譯成一個(gè)Content-Type為application/json.該參數(shù)可以用于在controller中為每個(gè)_format渲染一個(gè)不同的模板。它是一個(gè)很強(qiáng)的方式來(lái)渲染同一個(gè)內(nèi)容到不同的格式。
特殊的路由參數(shù):
正如你所看到的,每一個(gè)路由參數(shù)或者默認(rèn)值最終都是作為一個(gè)controller方法輸入?yún)?shù)被使用。另外,有三個(gè)參數(shù)比較特別,它們每一個(gè)都在你的應(yīng)用程序中增加一個(gè)唯一功能。
_controller: 這個(gè)參數(shù)決定了當(dāng)路由匹配時(shí),哪個(gè)controller被執(zhí)行。
_format: 用于設(shè)置請(qǐng)求格式。
_locale: 用于在session上設(shè)置本地化。
Controller的命名模式:
每一個(gè)路由必須有一個(gè)_controller參數(shù),它決定了當(dāng)路由匹配時(shí)哪個(gè)controller應(yīng)該被執(zhí)行。該參數(shù)使用單一的字符串模式,被稱(chēng)為logical controller name。
通過(guò)它Symfony可以映射到一個(gè)特定的PHP方法和類(lèi)。該模式有三部分,每一部分用冒號(hào)分割開(kāi):
bundle:controller:action
比如_controller 的值為 AcmeBlogBundle:Blog:show 意思是AcmeBlogBundle bundle中BlogController類(lèi)里面的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會(huì)自動(dòng)把它們的添加相應(yīng)的后綴,Blog=>BlogController, show => showAction。
你也可以使用它的完全限定名和方法來(lái)給_controller賦值,Acme\BlogBundle\Controller\BlogController::showAction 但一般為了簡(jiǎn)潔靈活而是用邏輯名稱(chēng)。另外除了上面兩種形式外,Symfony還支持第三種方式只有一個(gè)冒號(hào)分割符,如service_name:indexAction來(lái)為_(kāi)controller賦一個(gè)作為服務(wù)使用的controller。
路由參數(shù)和控制器參數(shù)
路由參數(shù)非常重要,因?yàn)槊恳粋€(gè)路由參數(shù)都會(huì)轉(zhuǎn)變成一個(gè)控制器參數(shù)被在方法中使用。
public function showAction($slug) { // ... }
事實(shí)上,全部的defaults集合和表單的參數(shù)值合并到一個(gè)單獨(dú)的數(shù)組中。這個(gè)數(shù)組中的每個(gè)鍵都會(huì)成為controller方法的參數(shù)。換句話(huà)說(shuō),你的controller方法的每一個(gè)參數(shù),Symfony都會(huì)從路由參數(shù)中查找并把找到的值賦給給參數(shù)。上面例子中的變量 $culture, $year,$title,$_format,$_controller 都會(huì)作為showAction()方法的參數(shù)。因?yàn)檎嘉环蚫efaults集合被合并到一起,即使$_controller變量也是一樣。你也可以使用一個(gè)特殊的變量$_route 來(lái)指定路由的名稱(chēng)。
包括外部路由資源
所有的路由資源的都是通過(guò)一個(gè)單一的配置文件導(dǎo)入的。通常是app/config/routing.yml。當(dāng)然你可能想從別處導(dǎo)入路由資源,比如你定義的bundle中的路由資源,你可以這樣導(dǎo)入:
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導(dǎo)入資源時(shí),鍵(比如acme_hello)是沒(méi)有意義的,只是用來(lái)保證該資源唯一不被其它行覆蓋。使用resources key加載給定的路由資源。在這個(gè)示例中資源是一個(gè)全路徑文件,@AcmeHelloBundle是簡(jiǎn)寫(xiě)語(yǔ)法,它會(huì)被指向bundle路徑。被導(dǎo)入的文件內(nèi)容如下:
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;
這個(gè)文件中的路由會(huì)被解析并跟主要的路由文件內(nèi)容一起被加載。
給導(dǎo)入的路由資源添加前綴
你可以為導(dǎo)入的路由資源選擇一個(gè)前綴,比如說(shuō)假設(shè)你想acme_hello路由有一個(gè)這樣的 匹配模式:/admin/hello/{name} 而不是直接的 /hello/{name}
那么你在導(dǎo)入它的時(shí)候可以為其指定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;
當(dāng)該外部路由資源加載的時(shí)候字符串 /admin 將被插入到匹配模式的前面。
可視化并調(diào)試路由
當(dāng)你添加和個(gè)性化路由時(shí),能夠看到它并能獲取一些細(xì)節(jié)信息將是非常有用的。一個(gè)好的查看你應(yīng)用程序的路由的方法是通過(guò)router:debug 命令行工具。
在你項(xiàng)目目錄下執(zhí)行如下命令:
$ php app/console router:debug
將會(huì)輸出你應(yīng)用程序的所有路由。你也可以在該命令后面添加某個(gè)路由的名字來(lái)獲取單個(gè)路由信息
$ php app/console router:debug article_show
生成URL
一個(gè)路由系統(tǒng)應(yīng)該也能用來(lái)生成URL。事實(shí)上,路由系統(tǒng)是一個(gè)雙向的系統(tǒng),映射URL到controller+parameters 和 回對(duì)應(yīng)到 一個(gè)URL??梢允褂胢atch()和generate()方法來(lái)操作。比如:
$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
要生成一個(gè)URL,你需要指定路由的名稱(chēng)(比如 blog_show)和任意的通配符(比如:slug=my-blog-post)作為參數(shù)。通過(guò)這些信息,可以生成任意的URL。
class MainController extends Controller { public function showAction($slug) { // ... $url = $this->get('router')->generate('blog_show', array('slug' => 'my-blog-post')); } }
那么如何從模板內(nèi)部來(lái)生成URL呢?如果你的應(yīng)用程序前端使用了AJAX請(qǐng)求,你也許想能夠基于你的路由配置在javascript中生成URL,通過(guò)使用
FOSJsRoutingBundle(https://github.com/FriendsOfSymfony/FOSJsRoutingBundle) 你可以做到:
var url = Routing.generate('blog_show', { "slug": 'my-blog-post'});
生成絕對(duì)路徑的URL
默認(rèn)的情況下,路由器生成相對(duì)路徑的URL(比如 /blog).要生成一個(gè)絕對(duì)路徑的URL,只需要傳入一個(gè)true到generate方法作為第三個(gè)參數(shù)值即可。
$router->generate('blog_show', array('slug' => 'my-blog-post'), true); // http://www.example.com/blog/my-blog-post
當(dāng)生成一個(gè)絕對(duì)路徑URL時(shí)主機(jī)是當(dāng)前請(qǐng)求對(duì)象的主機(jī),這個(gè)是基于PHP提供的服務(wù)器信息自動(dòng)決定的。當(dāng)你需要為運(yùn)行子命令行的腳本生成一個(gè)絕對(duì)URL時(shí),你需要在Request對(duì)象上手動(dòng)設(shè)置期望的主機(jī)頭。
$request->headers->set('HOST', 'www.example.com');
生成帶有查詢(xún)字符串的URL
generate()帶有一個(gè)數(shù)組通配符值來(lái)生成URI。 但是如果你傳入額外的值,它將被添加到URI作為查詢(xún)字符串:
$router->generate('blog', array('page' => 2, 'category' => 'Symfony')); // /blog/2?category=Symfony
從模板中生成URL
最常用到生成URL的地方是從模板中鏈接兩個(gè)頁(yè)面時(shí),這來(lái)需要使用一個(gè)模板幫助函數(shù):
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>
也可以生成絕對(duì)路徑:
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>
強(qiáng)制路由使用HTTPS或者HTTP
有時(shí)候?yàn)榱税踩鹨?jiàn),你需要你的站點(diǎn)必須使用HTTPS協(xié)議訪(fǎng)問(wèn)。這時(shí)候路由組件可以通過(guò)_scheme 約束來(lái)強(qiáng)迫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;
上面的路由定義就是強(qiáng)迫secure路由使用HTTPS協(xié)議訪(fǎng)問(wèn)。
反之,當(dāng)生成secure 的URL的時(shí)候,路由系統(tǒng)會(huì)根據(jù)當(dāng)前的訪(fǎng)問(wèn)協(xié)議方案生成相應(yīng)的訪(fǎng)問(wèn)協(xié)議。比如當(dāng)前是HTTP,則會(huì)自動(dòng)生成HTTPS訪(fǎng)問(wèn);如果是HTTPS訪(fǎng)問(wèn),那么就也會(huì)相應(yīng)的生成HTTPS訪(fǎng)問(wèn)。
# 如果方案是 HTTPS {{ path('secure') }} # 生成 /secure # 如果方案是 HTTP {{ path('secure') }} # 生成 https://example.com/secure
當(dāng)然你也可以通過(guò)設(shè)置_scheme為HTTP,來(lái)強(qiáng)制使用HTTP訪(fǎng)問(wèn)協(xié)議。除了上面說(shuō)的強(qiáng)迫使用HTTPS協(xié)議訪(fǎng)問(wèn)的設(shè)置方法外,還有一種用于站點(diǎn)區(qū)域設(shè)置
使用requires_channel 比如你想讓你站點(diǎn)中/admin 下面的所有路由都必須使用HTTPS協(xié)議訪(fǎng)問(wèn),或者你的安全路由定義在第三方bundle時(shí)使用。
總結(jié):
路由系統(tǒng)是一個(gè)為將接收的請(qǐng)求URL映射到被調(diào)用來(lái)處理該請(qǐng)求的controller函數(shù)的系統(tǒng)。它既能夠讓你生成漂亮的URL同時(shí)又能保持你的應(yīng)用程序功能跟這些URL解耦。路由系統(tǒng)是雙向機(jī)制的,也就是說(shuō)它們也可以用來(lái)生成URL。
希望本文所述對(duì)大家基于Symfony框架的PHP程序設(shè)計(jì)有所幫助。
- 高性能PHP框架Symfony2經(jīng)典入門(mén)教程
- Symfony2使用Doctrine進(jìn)行數(shù)據(jù)庫(kù)查詢(xún)方法實(shí)例總結(jié)
- Symfony2實(shí)現(xiàn)從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)的方法小結(jié)
- Symfony2之session與cookie用法小結(jié)
- Symfony2創(chuàng)建頁(yè)面實(shí)例詳解
- Symfony2安裝第三方Bundles實(shí)例詳解
- Symfony2聯(lián)合查詢(xún)實(shí)現(xiàn)方法
- Symfony2實(shí)現(xiàn)在controller中獲取url的方法
- Symfony2在Nginx下的配置方法圖文教程
- Symfony2 session用法實(shí)例分析
- Symfony2創(chuàng)建基于域名的路由相關(guān)示例
相關(guān)文章
PHP統(tǒng)計(jì)二維數(shù)組元素個(gè)數(shù)的方法
數(shù)據(jù)表里面的字段 content 存儲(chǔ)了一個(gè)以逗號(hào)分割的字符串,最大有20個(gè)數(shù),最大數(shù)字為40。比如3,24,33,40類(lèi)似字樣的數(shù)字序列。其實(shí)就是一個(gè)保存了多項(xiàng)投票結(jié)果的字段啦?,F(xiàn)在需要統(tǒng)計(jì)每個(gè)數(shù)字的個(gè)數(shù),也就是每個(gè)投票項(xiàng)有多少人投了,并排序2013-11-11thinkPHP框架單元測(cè)試庫(kù)tpunit用法示例
這篇文章主要介紹了thinkPHP框架單元測(cè)試庫(kù)tpunit用法,結(jié)合實(shí)例形式分析了tpunit簡(jiǎn)單使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2018-08-08laravel 解決ajax異步提交數(shù)據(jù),并還回填充表格的問(wèn)題
今天小編就為大家分享一篇laravel 解決ajax異步提交數(shù)據(jù),并還回填充表格的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10PHP設(shè)計(jì)模式之工廠(chǎng)模式(Factory)入門(mén)與應(yīng)用詳解
這篇文章主要介紹了PHP設(shè)計(jì)模式之工廠(chǎng)模式(Factory),結(jié)合實(shí)例形式詳細(xì)分析了PHP工廠(chǎng)模式的概念、原理、基本應(yīng)用與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-12-12ThinkPHP連接數(shù)據(jù)庫(kù)的方式匯總
這篇文章主要介紹了ThinkPHP連接數(shù)據(jù)庫(kù)的方式,包括項(xiàng)目配置文件定義、DSN方式傳參、數(shù)組傳參、模型類(lèi)里定義等,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-12-12YII2 實(shí)現(xiàn)多語(yǔ)言配置的方法分享
這篇文章主要介紹了YII2實(shí)現(xiàn)多語(yǔ)言配置的方法,文中YII2的版本是2.0.7,可能會(huì)與其他教程有不同,有需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-01-01使用CodeIgniter的類(lèi)庫(kù)做圖片上傳
CodeIgniter的文件上傳類(lèi)允許文件被上傳。您可以設(shè)置指定上傳某類(lèi)型的文件及指定大小的文件。這篇文章主要介紹了使用CodeIgniter的類(lèi)庫(kù)做圖片上傳,需要的朋友可以參考下2014-06-06thinkphp驗(yàn)證碼顯示不出來(lái)的解決方法
這篇文章主要介紹了thinkphp驗(yàn)證碼顯示不出來(lái)的解決方法,需要的朋友可以參考下2014-03-03