摘要:路由漂亮的是任何嚴謹的應用程序所必須的這意味著像這樣丑陋的要被所取代具有靈活性更加重要如果你需要將更改為需要做些什么你需要搜索并更新多少鏈接才能做出這種改動如果你使用的是的路由更改將是很簡單的創建路由路由是從到控制器的映射假如你想要一個
路由
漂亮的URL是任何嚴謹的Web應用程序所必須的. 這意味著像 index.php?article_id=57 這樣丑陋的URL要被 /read/intro-to-symfony 所取代.
具有靈活性更加重要. 如果你需要將 /blog 更改為 /news , 需要做些什么? 你需要搜索并更新多少鏈接才能做出這種改動? 如果你使用的是Symfony的路由, 更改將是很簡單的.
創建路由路由是從URL到控制器的映射, 假如你想要一個路由完全匹配 /blog 和另外更多可匹配任何像 /blog/my-post 和 /blog/all-about-symfony URL的動態路由.
路由可以在YAML, XML和PHP. 所有格式都提供相同的功能和性能, 因此可選擇你喜歡的格式. 如果你選擇PHP annotations, 請在你的應用程序中運行一次此命令以添加對它們的支持:
$ composer require annotations
現在你可以配置路由:
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() 將被執行;
如果用戶訪問 /blog/* , 匹配第二條路由配置并且 show() 將被執行. 因為路由路徑是 /blog/{slug}, 所以 $slug 變量傳遞給該值匹配的 show() . 例如, 如果用戶訪問 /blog/yay-routing , 那么 $slug 將等于 yay-routing .
每當路由路徑中有 {placeholder} 時, 該部分就成為通配符: 它將匹配任意值. 你的控制器現在也有一個名為 $placeholder 的參數 ( 通配符和參數名稱必須匹配 ).
每個路由還有一個內部名稱: blog_list 和 blog_show . 這些可以是任意內容 ( 只要每個都是唯一的 ) 并且需要無任何特別含義. 稍后你將使用它們來生成URL.
其他格式的路由本地化路由(i18n)每個方法上面的 @Route 稱為 annotation. 如果你更愿意使用YAML, XML或PHP配置路由, 那沒問題! 只需創建一個新的路由文件 ( 例如 routes.xml ) , Symfony就會自動使用它.
路由可以本地化地為每個區域提供唯一的路徑. Symfony提供了一種簡便的方式來聲明本地化路由而無重復.
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"); };
當本地化路由匹配時, Symfony會自動識別請求期間應使用哪個區域的路由設置. 以這種方式定義路由避免了對路由重復注冊的需要, 最小化了由定義不一致引起的任何錯誤的風險.
為所有路由添加前綴是國際化應用程序的一個常見需求. 這樣可以通過為每個語言環境定義不同的路徑前綴來完成 ( 如果愿意, 可以為默認語言設置一個空前綴 ):
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 路由將包含一個博客主題的分頁列表, 其中包含 /blog/2 和 /blog/3 等第2頁和第3頁的URL. 如果你將路徑修改為 /blog/{page} , 你將會遇到一個問題:
blog_list: /blog/{page} 將匹配 /blog/*;
blog_show: /blog/{slug} 將仍然匹配 /blog/*;
當兩條路由匹配相同的URL時, 加載的第一條路由將勝利. 不幸的是, 這意味著 /blog/yay-routing 將匹配 blog_list.
要解決此問題, 添加一個 {page} 通配符用來只匹配數字:
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+ 是一個匹配任意長度數字的正則表達式. 現在:
URL | Route | Parameters |
---|---|---|
/blog/2 | blog_list | $page = 2 |
/blog/yay-routing | blog_show | $slug = yay-routing |
如果你愿意, 可以在每個占位符中使用語法 {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方法, 主機名和動態表達式 ) 請參閱 How to Define Route Requirements
給{占位符}一個默認值在前面的例子中, blog_list 的路徑為 /blog/{page} . 如果用戶訪問 /blog/1 , 則會匹配. 如果用戶訪問 /blog , 將無法匹配. 只要向路由路徑添加了 {占位符} , 它就必須有值.
那么當用戶訪問 /blog 時, 如何讓 blog_list 再次匹配呢? 通過添加一個 默認 值:
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;
現在, 當用戶訪問 /blog 時, blog_list 路由會匹配, 并且 $page 路由參數會默認取值為 1 .
與{通配符}條件一樣, 使用語法 {placeholder_name?default_value} 也可以在每個占位符中內聯默認值. 此功能與內聯條件兼容, 因此你可以在一個占位符中內聯:
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?} ) .全部路由列表
隨著你應用程序的健壯, 最終會有大量的路由被定義! 要查看所有內容, 請運行命令:
$ 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;
如你所見, 只有當URL的 {_locale} 部分為 en 或 fr 且 {year} 為數字時, 此路由才會匹配. 示例還展示了如何在占位符之間使用 . 號來替換 / . 以下URL都可匹配:
/articles/en/2010/my-post
/articles/fr/2010/my-post.rss
/articles/en/2013/my-latest-post.html
_format 路由參數特殊路由參數示例突出顯示了 _format 特殊路由參數, 當使用此參數時, 匹配的值將成為Request對象的"請求格式".
最后, 請求格式被用作設置返回 Content-Type 之類的事情 ( 例如: 一個JSON請求格式會轉換 Content-Type 為 application/json )
如你所見, 每個路由參數或默認值最終都可以作為控制器方法的參數. 此外, 還有四個特殊參數: 每個參數在應用程序中具有獨特的功能:
_controller
?? 用于確定路由匹配時執行的控制器
_format
?? 用于設置請求格式 ( 閱讀更多 )
_fragment
?? 用于設置fragment identifier, URL的最后可選部分, 以 # 字符開頭, 用于標識文檔的某一部分.
_locale
?? 用于在請求上設置區域 ( 閱讀更多 )
尾部斜杠重定向URL從歷史上看, URL遵循UNIX約定, 即為路徑添加尾部斜杠 ( 例如 https://example.com/foo/ ) , 當刪除斜杠時將作為文件引用 ( https://example.com/foo ) . 雖然為兩個URL提供不同的內容是可以的, 但現在將兩個URL視為相同的URL并在他們之間重定向是很常見的.
Symfony遵循這個邏輯, 在帶斜杠和不帶斜杠的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) |
如果你的應用程序為每個路徑 ( /foo 和 /foo/ ) 定義了不同的路由, 則不會發生自動重定向, 并且始終匹配正確的路由.控制器命名模式在Symfony4.1中引入了從 /foo/ 到 /foo 的自動301重定向. 在之前的Symfony版本中, 會響應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
路由系統也可以生成URL. 實際上, 路由是雙向系統: 將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") ); } }
如果需要從服務生成URL, 注入 UrlGeneratorInterface 服務.
// 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() 方法采用通配符數組來生成URI. 但是如果你傳遞額外值, 他們將作為查詢字符串添加到URI中.
$this->router->generate("blog", array( "page" => 2, "category" => "Symfony", )); // /blog/2?category=Symfony生成本地化URL
路由本地化時, Symfony默認使用當前請求區域來生成URL. 為了生成不同語言環境的URL, 你必須在parameters數組中傳遞 _locale :
$this->router->generate("about_us", array( "_locale" => "nl", )); // generates: /over-ons從模板中生成URL
要在Twig中生成URL: 請參閱模板章節. 如果你需要在JavaScript中生成URL, 請參閱 How to Generate Routing URLs in JavaScript
生成絕對URL默認情況下, 路由將生成相對URL ( 例如 /blog ) . 在控制器中, 將 UrlGeneratorInterface::ABSOLUTE_URL 傳遞給 generateUrl() 方法的第三個參數:
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.錯誤排除
以下是使用路由時可能會遇到的一些常見錯誤:
Controller "AppControllerBlogController::show()" requires that you provide a value for the "$slug" argument.
當你的控制器方法有一個參數 ( 例如 $slug ) 時會發生這種情況:
public function show($slug) { // .. }
你的路由沒有 {slug} 通配符 ( 例如 /blog/show ). 在你的路由路徑中增加 {slug} : /blog/show/{slug} 或為參數設置一個默認值 ( 例如 $slug = null )
Some mandatory parameters are missing ("slug") to generate a URL for route "blog_show".
這意味著你正在嘗試生成 blog_show 路由的URL, 但你沒有傳遞 slug 值 (這是必須的, 因為在路由路徑中有一個 {slug} 通配符). 要解決此問題, 請在生成路由時傳遞 slug 值:
$this->generateUrl("blog_show", array("slug" => "slug-value")); // or, in Twig // {{ path("blog_show", {"slug": "slug-value"}) }}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29721.html
摘要:創建你的第一個頁面創建一個新頁面無論是頁面還是端點分為兩步創建一個路由路由是一個指向你的頁面比如同時它映射到一個控制器創建一個控制器控制器是你為了構造頁面而寫的功能獲取傳入的請求信息并用它創建一個對象該對象可以包含內容字符串甚至是圖像或 創建你的第一個Symfony頁面 創建一個新頁面 - 無論是HTML頁面還是JSON端點 - 分為兩步: 創建一個路由: 路由(route)是一個指...
摘要:安裝和設置框架要創建新的應用程序首先確保使用的是或更高版本并且已經安裝如果未安裝請首先在系統上全局安裝如果你想使用虛擬機請查看通過運行以下命令來創建新項目這將創建一個新的目錄下載所需的依賴,甚至生成你所需的基本目錄和文件換句話說你的 安裝和設置Symfony框架 要創建新的Symfony應用程序, 首先確保使用的是PHP7.1 或更高版本并且已經安裝Componser. 如果未安裝, ...
摘要:使用承諾和異步功能來擺脫回調地獄的應用程序,并簡化錯誤處理。它暴露了自己的和對象,而不是的和對象。因此,可被視為的模塊的抽象,其中是的應用程序框架。這使得中間件對于整個堆棧而言不僅僅是最終應用程序代碼,而且更易于書寫,并更不容易出錯。 Koa 與 Express 此系列文章的應用示例已發布于 GitHub: koa-docs-Zh-CN. 可以 Fork 幫助改進或 Star 關注更新...
摘要:常見問題此系列文章的應用示例已發布于可以幫助改進或關注更新歡迎替代它更像是,但是很多的好東西被轉移到的中間件級別,以幫助形成更強大的基礎。這使得中間件對于整個堆棧而言不僅僅是最終應用程序代碼,而且更易于書寫,并更不容易出錯。 常見問題 此系列文章的應用示例已發布于 GitHub: koa-docs-Zh-CN. 可以 Fork 幫助改進或 Star 關注更新. 歡迎 Star. Koa...
閱讀 824·2021-09-07 09:58
閱讀 2682·2021-08-31 09:42
閱讀 2855·2019-08-30 14:18
閱讀 3086·2019-08-30 14:08
閱讀 1831·2019-08-30 12:57
閱讀 2759·2019-08-26 13:31
閱讀 1299·2019-08-26 11:58
閱讀 1052·2019-08-23 18:06