摘要:路由漂亮的是任何嚴(yán)謹(jǐn)?shù)膽?yīng)用程序所必須的這意味著像這樣丑陋的要被所取代具有靈活性更加重要如果你需要將更改為需要做些什么你需要搜索并更新多少鏈接才能做出這種改動(dòng)如果你使用的是的路由更改將是很簡單的創(chuàng)建路由路由是從到控制器的映射假如你想要一個(gè)
路由
漂亮的URL是任何嚴(yán)謹(jǐn)?shù)腤eb應(yīng)用程序所必須的. 這意味著像 index.php?article_id=57 這樣丑陋的URL要被 /read/intro-to-symfony 所取代.
具有靈活性更加重要. 如果你需要將 /blog 更改為 /news , 需要做些什么? 你需要搜索并更新多少鏈接才能做出這種改動(dòng)? 如果你使用的是Symfony的路由, 更改將是很簡單的.
創(chuàng)建路由路由是從URL到控制器的映射, 假如你想要一個(gè)路由完全匹配 /blog 和另外更多可匹配任何像 /blog/my-post 和 /blog/all-about-symfony URL的動(dòng)態(tài)路由.
路由可以在YAML, XML和PHP. 所有格式都提供相同的功能和性能, 因此可選擇你喜歡的格式. 如果你選擇PHP annotations, 請?jiān)谀愕膽?yīng)用程序中運(yùn)行一次此命令以添加對它們的支持:
$ composer require annotations
現(xiàn)在你可以配置路由:
Annotations
// src/Controller/BlogController.php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentRoutingAnnotationRoute; class BlogController extends AbstractController { /** * Matches /blog exactly * * @Route("/blog", name="blog_list") */ public function list() { // ... } /** * Matches /blog/* * * @Route("/blog/{slug}", name="blog_show") */ public function show($slug) { // $slug will equal the dynamic part of the URL // e.g. at /blog/yay-routing, then $slug="yay-routing" // ... } }
YAML
# config/routes.yaml blog_list: path: /blog controller: AppControllerBlogController::list blog_show: path: /blog/{slug} controller: AppControllerBlogController::show
XML
PHP
// config/routes.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use AppControllerBlogController; $routes = new RouteCollection(); $routes->add("blog_list", new Route("/blog", array( "_controller" => [BlogController::class, "list"] ))); $routes->add("blog_show", new Route("/blog/{slug}", array( "_controller" => [BlogController::class, "show"] ))); return $routes;
感謝這兩條路由:
如果用戶訪問 /blog , 匹配第一條路由配置并且 list() 將被執(zhí)行;
如果用戶訪問 /blog/* , 匹配第二條路由配置并且 show() 將被執(zhí)行. 因?yàn)槁酚陕窂绞?/blog/{slug}, 所以 $slug 變量傳遞給該值匹配的 show() . 例如, 如果用戶訪問 /blog/yay-routing , 那么 $slug 將等于 yay-routing .
每當(dāng)路由路徑中有 {placeholder} 時(shí), 該部分就成為通配符: 它將匹配任意值. 你的控制器現(xiàn)在也有一個(gè)名為 $placeholder 的參數(shù) ( 通配符和參數(shù)名稱必須匹配 ).
每個(gè)路由還有一個(gè)內(nèi)部名稱: blog_list 和 blog_show . 這些可以是任意內(nèi)容 ( 只要每個(gè)都是唯一的 ) 并且需要無任何特別含義. 稍后你將使用它們來生成URL.
其他格式的路由本地化路由(i18n)每個(gè)方法上面的 @Route 稱為 annotation. 如果你更愿意使用YAML, XML或PHP配置路由, 那沒問題! 只需創(chuàng)建一個(gè)新的路由文件 ( 例如 routes.xml ) , Symfony就會(huì)自動(dòng)使用它.
路由可以本地化地為每個(gè)區(qū)域提供唯一的路徑. Symfony提供了一種簡便的方式來聲明本地化路由而無重復(fù).
Annotations
// src/Controller/CompanyController.php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentRoutingAnnotationRoute; class CompanyController extends AbstractController { /** * @Route({ * "nl": "/over-ons", * "en": "/about-us" * }, name="about_us") */ public function about() { // ... } }
YAML
# config/routes.yaml about_us: path: nl: /over-ons en: /about-us controller: AppControllerCompanyController::about
XML
/over-ons /about-us
PHP
// config/routes.php namespace SymfonyComponentRoutingLoaderConfigurator; return function (RoutingConfigurator $routes) { $routes->add("about_us", ["nl" => "/over-ons", "en" => "/about-us"]) ->controller("AppControllerCompanyController::about"); };
當(dāng)本地化路由匹配時(shí), Symfony會(huì)自動(dòng)識別請求期間應(yīng)使用哪個(gè)區(qū)域的路由設(shè)置. 以這種方式定義路由避免了對路由重復(fù)注冊的需要, 最小化了由定義不一致引起的任何錯(cuò)誤的風(fēng)險(xiǎn).
為所有路由添加前綴是國際化應(yīng)用程序的一個(gè)常見需求. 這樣可以通過為每個(gè)語言環(huán)境定義不同的路徑前綴來完成 ( 如果愿意, 可以為默認(rèn)語言設(shè)置一個(gè)空前綴 ):
YAML
# config/routes/annotations.yaml controllers: resource: "../../src/Controller/" type: annotation prefix: en: "" # don"t prefix URLs for English, the default locale nl: "/nl"添加 {通配符} 條件
想象一下, blog_list 路由將包含一個(gè)博客主題的分頁列表, 其中包含 /blog/2 和 /blog/3 等第2頁和第3頁的URL. 如果你將路徑修改為 /blog/{page} , 你將會(huì)遇到一個(gè)問題:
blog_list: /blog/{page} 將匹配 /blog/*;
blog_show: /blog/{slug} 將仍然匹配 /blog/*;
當(dāng)兩條路由匹配相同的URL時(shí), 加載的第一條路由將勝利. 不幸的是, 這意味著 /blog/yay-routing 將匹配 blog_list.
要解決此問題, 添加一個(gè) {page} 通配符用來只匹配數(shù)字:
Annotations
// src/Controller/BlogController.php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentRoutingAnnotationRoute; class BlogController extends AbstractController { /** * @Route("/blog/{page}", name="blog_list", requirements={"page"="d+"}) */ public function list($page) { // ... } /** * @Route("/blog/{slug}", name="blog_show") */ public function show($slug) { // ... } }
YAML
# config/routes.yaml blog_list: path: /blog/{page} controller: AppControllerBlogController::list requirements: page: "d+" blog_show: # ...
XML
d+
PHP
// config/routes.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use AppControllerBlogController; $routes = new RouteCollection(); $routes->add("blog_list", new Route("/blog/{page}", array( "_controller" => [BlogController::class, "list"], ), array( "page" => "d+" ))); // ... return $routes;
d+ 是一個(gè)匹配任意長度數(shù)字的正則表達(dá)式. 現(xiàn)在:
URL | Route | Parameters |
---|---|---|
/blog/2 | blog_list | $page = 2 |
/blog/yay-routing | blog_show | $slug = yay-routing |
如果你愿意, 可以在每個(gè)占位符中使用語法 {placeholder_name
Annotations
// src/Controller/BlogController.php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentRoutingAnnotationRoute; class BlogController extends AbstractController { /** * @Route("/blog/{page}", name="blog_list") */ public function list($page) { // ... } }
YAML
# config/routes.yaml blog_list: path: /blog/{page} controller: AppControllerBlogController::list
XML
PHP
// config/routes.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use AppControllerBlogController; $routes = new RouteCollection(); $routes->add("blog_list", new Route("/blog/{page}", array( "_controller" => [BlogController::class, "list"], ))); // ... return $routes;
要了解其他路由條件 ( 如HTTP方法, 主機(jī)名和動(dòng)態(tài)表達(dá)式 ) 請參閱 How to Define Route Requirements
給{占位符}一個(gè)默認(rèn)值在前面的例子中, blog_list 的路徑為 /blog/{page} . 如果用戶訪問 /blog/1 , 則會(huì)匹配. 如果用戶訪問 /blog , 將無法匹配. 只要向路由路徑添加了 {占位符} , 它就必須有值.
那么當(dāng)用戶訪問 /blog 時(shí), 如何讓 blog_list 再次匹配呢? 通過添加一個(gè) 默認(rèn) 值:
Annotations
// src/Controller/BlogController.php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentRoutingAnnotationRoute; class BlogController extends AbstractController { /** * @Route("/blog/{page}", name="blog_list", requirements={"page"="d+"}) */ public function list($page = 1) { // ... } }
YAML
# config/routes.yaml blog_list: path: /blog/{page} controller: AppControllerBlogController::list defaults: page: 1 requirements: page: "d+" blog_show: # ...
XML
1 d+
PHP
// config/routes.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use AppControllerBlogController; $routes = new RouteCollection(); $routes->add("blog_list", new Route( "/blog/{page}", array( "_controller" => [BlogController::class, "list"], "page" => 1, ), array( "page" => "d+" ) )); // ... return $routes;
現(xiàn)在, 當(dāng)用戶訪問 /blog 時(shí), blog_list 路由會(huì)匹配, 并且 $page 路由參數(shù)會(huì)默認(rèn)取值為 1 .
與{通配符}條件一樣, 使用語法 {placeholder_name?default_value} 也可以在每個(gè)占位符中內(nèi)聯(lián)默認(rèn)值. 此功能與內(nèi)聯(lián)條件兼容, 因此你可以在一個(gè)占位符中內(nèi)聯(lián):
Annotations
// src/Controller/BlogController.php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentRoutingAnnotationRoute; class BlogController extends AbstractController { /** * @Route("/blog/{page?1}", name="blog_list") */ public function list($page) { // ... } }
YAML
# config/routes.yaml blog_list: path: /blog/{page?1} controller: AppControllerBlogController::list
XML
PHP
// config/routes.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use AppControllerBlogController; $routes = new RouteCollection(); $routes->add("blog_list", new Route("/blog/{page?1}", array( "_controller" => [BlogController::class, "list"], ))); // ... return $routes;
占位符變量的值若是 null 變量, 則需要在通配符最后添加 ? 字符. ( 例如 /blog/{page?} ) .全部路由列表
隨著你應(yīng)用程序的健壯, 最終會(huì)有大量的路由被定義! 要查看所有內(nèi)容, 請運(yùn)行命令:
$ php bin/console debug:router ------------------------------ -------- ------------------------------------- Name Method Path ------------------------------ -------- ------------------------------------- app_lucky_number ANY /lucky/number/{max} ... ------------------------------ -------- -------------------------------------高級路由示例
請查看高級示例:
Annotations
// src/Controller/ArticleController.php // ... class ArticleController extends AbstractController { /** * @Route( * "/articles/{_locale}/{year}/{slug}.{_format}", * defaults={"_format": "html"}, * requirements={ * "_locale": "en|fr", * "_format": "html|rss", * "year": "d+" * } * ) */ public function show($_locale, $year, $slug) { } }
YAML
# config/routes.yaml article_show: path: /articles/{_locale}/{year}/{slug}.{_format} controller: AppControllerArticleController::show defaults: _format: html requirements: _locale: en|fr _format: html|rss year: d+
XML
html en|fr html|rss d+
PHP
// config/routes.php use SymfonyComponentRoutingRouteCollection; use SymfonyComponentRoutingRoute; use AppControllerArticleController; $routes = new RouteCollection(); $routes->add( "article_show", new Route("/articles/{_locale}/{year}/{slug}.{_format}", array( "_controller" => [ArticleController::class, "show"], "_format" => "html", ), array( "_locale" => "en|fr", "_format" => "html|rss", "year" => "d+", )) ); return $routes;
如你所見, 只有當(dāng)URL的 {_locale} 部分為 en 或 fr 且 {year} 為數(shù)字時(shí), 此路由才會(huì)匹配. 示例還展示了如何在占位符之間使用 . 號來替換 / . 以下URL都可匹配:
/articles/en/2010/my-post
/articles/fr/2010/my-post.rss
/articles/en/2013/my-latest-post.html
_format 路由參數(shù)特殊路由參數(shù)示例突出顯示了 _format 特殊路由參數(shù), 當(dāng)使用此參數(shù)時(shí), 匹配的值將成為Request對象的"請求格式".
最后, 請求格式被用作設(shè)置返回 Content-Type 之類的事情 ( 例如: 一個(gè)JSON請求格式會(huì)轉(zhuǎn)換 Content-Type 為 application/json )
如你所見, 每個(gè)路由參數(shù)或默認(rèn)值最終都可以作為控制器方法的參數(shù). 此外, 還有四個(gè)特殊參數(shù): 每個(gè)參數(shù)在應(yīng)用程序中具有獨(dú)特的功能:
_controller
?? 用于確定路由匹配時(shí)執(zhí)行的控制器
_format
?? 用于設(shè)置請求格式 ( 閱讀更多 )
_fragment
?? 用于設(shè)置fragment identifier, URL的最后可選部分, 以 # 字符開頭, 用于標(biāo)識文檔的某一部分.
_locale
?? 用于在請求上設(shè)置區(qū)域 ( 閱讀更多 )
尾部斜杠重定向URL從歷史上看, URL遵循UNIX約定, 即為路徑添加尾部斜杠 ( 例如 https://example.com/foo/ ) , 當(dāng)刪除斜杠時(shí)將作為文件引用 ( https://example.com/foo ) . 雖然為兩個(gè)URL提供不同的內(nèi)容是可以的, 但現(xiàn)在將兩個(gè)URL視為相同的URL并在他們之間重定向是很常見的.
Symfony遵循這個(gè)邏輯, 在帶斜杠和不帶斜杠的URL之間重定向 ( 但僅限于GET和HEAD請求 ):
Route path | If the requested URL is /foo | If the requested URL is /foo/ |
---|---|---|
/foo | It matches (200 status response) | It makes a 301 redirect to /foo |
/foo/ | It makes a 301 redirect to /foo/ | It matches (200 status response) |
如果你的應(yīng)用程序?yàn)槊總€(gè)路徑 ( /foo 和 /foo/ ) 定義了不同的路由, 則不會(huì)發(fā)生自動(dòng)重定向, 并且始終匹配正確的路由.控制器命名模式在Symfony4.1中引入了從 /foo/ 到 /foo 的自動(dòng)301重定向. 在之前的Symfony版本中, 會(huì)響應(yīng)404.
路由中的控制器格式非常簡單 CONTROLLER_CLASS::METHOD .
To refer to an action that is implemented as the __invoke() method of a controller class, you do not have to pass the method name, but can just use the fully qualified class name (e.g. AppControllerBlogController).生成URL
路由系統(tǒng)也可以生成URL. 實(shí)際上, 路由是雙向系統(tǒng): 將URL映射到控制器以及路由返解為URL.
要生成URL, 你需要制定路由的名稱 ( 例如 blog_show ) 以及該路由的路徑中使用的任何通配符 ( 例如 slug = my-blog-post ) . 有了這些信息, 可輕松生成任何URL:
class MainController extends AbstractController { public function show($slug) { // ... // /blog/my-blog-post $url = $this->generateUrl( "blog_show", array("slug" => "my-blog-post") ); } }
如果需要從服務(wù)生成URL, 注入 UrlGeneratorInterface 服務(wù).
// src/Service/SomeService.php use SymfonyComponentRoutingGeneratorUrlGeneratorInterface; class SomeService { private $router; public function __construct(UrlGeneratorInterface $router) { $this->router = $router; } public function someMethod() { $url = $this->router->generate( "blog_show", array("slug" => "my-blog-post") ); // ... } }使用查詢字符串生成URL
generate() 方法采用通配符數(shù)組來生成URI. 但是如果你傳遞額外值, 他們將作為查詢字符串添加到URI中.
$this->router->generate("blog", array( "page" => 2, "category" => "Symfony", )); // /blog/2?category=Symfony生成本地化URL
路由本地化時(shí), Symfony默認(rèn)使用當(dāng)前請求區(qū)域來生成URL. 為了生成不同語言環(huán)境的URL, 你必須在parameters數(shù)組中傳遞 _locale :
$this->router->generate("about_us", array( "_locale" => "nl", )); // generates: /over-ons從模板中生成URL
要在Twig中生成URL: 請參閱模板章節(jié). 如果你需要在JavaScript中生成URL, 請參閱 How to Generate Routing URLs in JavaScript
生成絕對URL默認(rèn)情況下, 路由將生成相對URL ( 例如 /blog ) . 在控制器中, 將 UrlGeneratorInterface::ABSOLUTE_URL 傳遞給 generateUrl() 方法的第三個(gè)參數(shù):
use SymfonyComponentRoutingGeneratorUrlGeneratorInterface; $this->generateUrl("blog_show", array("slug" => "my-blog-post"), UrlGeneratorInterface::ABSOLUTE_URL); // http://www.example.com/blog/my-blog-post
The host that"s used when generating an absolute URL is automatically detected using the current Request object. When generating absolute URLs from outside the web context (for instance in a console command) this doesn"t work. See How to Generate URLs from the Console to learn how to solve this problem.錯(cuò)誤排除
以下是使用路由時(shí)可能會(huì)遇到的一些常見錯(cuò)誤:
Controller "AppControllerBlogController::show()" requires that you provide a value for the "$slug" argument.
當(dāng)你的控制器方法有一個(gè)參數(shù) ( 例如 $slug ) 時(shí)會(huì)發(fā)生這種情況:
public function show($slug) { // .. }
你的路由沒有 {slug} 通配符 ( 例如 /blog/show ). 在你的路由路徑中增加 {slug} : /blog/show/{slug} 或?yàn)閰?shù)設(shè)置一個(gè)默認(rèn)值 ( 例如 $slug = null )
Some mandatory parameters are missing ("slug") to generate a URL for route "blog_show".
這意味著你正在嘗試生成 blog_show 路由的URL, 但你沒有傳遞 slug 值 (這是必須的, 因?yàn)樵诼酚陕窂街杏幸粋€(gè) {slug} 通配符). 要解決此問題, 請?jiān)谏陕酚蓵r(shí)傳遞 slug 值:
$this->generateUrl("blog_show", array("slug" => "slug-value")); // or, in Twig // {{ path("blog_show", {"slug": "slug-value"}) }}
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/29721.html
摘要:創(chuàng)建你的第一個(gè)頁面創(chuàng)建一個(gè)新頁面無論是頁面還是端點(diǎn)分為兩步創(chuàng)建一個(gè)路由路由是一個(gè)指向你的頁面比如同時(shí)它映射到一個(gè)控制器創(chuàng)建一個(gè)控制器控制器是你為了構(gòu)造頁面而寫的功能獲取傳入的請求信息并用它創(chuàng)建一個(gè)對象該對象可以包含內(nèi)容字符串甚至是圖像或 創(chuàng)建你的第一個(gè)Symfony頁面 創(chuàng)建一個(gè)新頁面 - 無論是HTML頁面還是JSON端點(diǎn) - 分為兩步: 創(chuàng)建一個(gè)路由: 路由(route)是一個(gè)指...
摘要:安裝和設(shè)置框架要?jiǎng)?chuàng)建新的應(yīng)用程序首先確保使用的是或更高版本并且已經(jīng)安裝如果未安裝請首先在系統(tǒng)上全局安裝如果你想使用虛擬機(jī)請查看通過運(yùn)行以下命令來創(chuàng)建新項(xiàng)目這將創(chuàng)建一個(gè)新的目錄下載所需的依賴,甚至生成你所需的基本目錄和文件換句話說你的 安裝和設(shè)置Symfony框架 要?jiǎng)?chuàng)建新的Symfony應(yīng)用程序, 首先確保使用的是PHP7.1 或更高版本并且已經(jīng)安裝Componser. 如果未安裝, ...
摘要:使用承諾和異步功能來擺脫回調(diào)地獄的應(yīng)用程序,并簡化錯(cuò)誤處理。它暴露了自己的和對象,而不是的和對象。因此,可被視為的模塊的抽象,其中是的應(yīng)用程序框架。這使得中間件對于整個(gè)堆棧而言不僅僅是最終應(yīng)用程序代碼,而且更易于書寫,并更不容易出錯(cuò)。 Koa 與 Express 此系列文章的應(yīng)用示例已發(fā)布于 GitHub: koa-docs-Zh-CN. 可以 Fork 幫助改進(jìn)或 Star 關(guān)注更新...
摘要:入門指南路由路由允許用戶為不同的端點(diǎn)指定處理程序函數(shù)。被訪問服務(wù)器的基本,最終被路由器匹配到處理程序函數(shù),測試,然后返回一個(gè)對象。請求參數(shù)將作為關(guān)鍵字參數(shù)傳遞給路線處理程序函數(shù)。例如所有有效的參數(shù)必須傳遞給以便構(gòu)建一個(gè)。 入門指南 Install Sanic:python3 -m pip install sanicexample from sanic import Sanic from...
摘要:常見問題此系列文章的應(yīng)用示例已發(fā)布于可以幫助改進(jìn)或關(guān)注更新歡迎替代它更像是,但是很多的好東西被轉(zhuǎn)移到的中間件級別,以幫助形成更強(qiáng)大的基礎(chǔ)。這使得中間件對于整個(gè)堆棧而言不僅僅是最終應(yīng)用程序代碼,而且更易于書寫,并更不容易出錯(cuò)。 常見問題 此系列文章的應(yīng)用示例已發(fā)布于 GitHub: koa-docs-Zh-CN. 可以 Fork 幫助改進(jìn)或 Star 關(guān)注更新. 歡迎 Star. Koa...
閱讀 843·2021-09-07 09:58
閱讀 2700·2021-08-31 09:42
閱讀 2873·2019-08-30 14:18
閱讀 3096·2019-08-30 14:08
閱讀 1843·2019-08-30 12:57
閱讀 2769·2019-08-26 13:31
閱讀 1311·2019-08-26 11:58
閱讀 1065·2019-08-23 18:06