搜尋
首頁後端開發php教程詳解Symfony2的系統路由

詳解Symfony2的系統路由

Jan 05, 2018 pm 05:46 PM
系統路由

本文主要介紹了Symfony2系統路由,詳細分析了Symfony路由原理及路由的創建,配置與使用技巧。需要的朋友可以參考下,希望對大家有幫助。

漂亮的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(&#39;blog_show&#39;, new Route(&#39;/blog/{slug}&#39;, array(
     &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:show&#39;,
)));

#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(&#39;AcmeBlogBundle:Blog:show.html.twig&#39;, array(
      &#39;blog&#39; => $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(&#39;framework&#39;, array(
  // ...
  &#39;router&#39;    => array(&#39;resource&#39; => &#39;%kernel.root_dir%/config/routing.php&#39;),
));

基礎路由設定

#定義一個路由很簡單,通常一個應用程式擁有很多路由。一個基礎路由是由兩個部分組成: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(&#39;_welcome&#39;, new Route(&#39;/&#39;, array(
  &#39;_controller&#39; => &#39;AcmeDemoBundle:Main:homepage&#39;,
)));
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(&#39;blog_show&#39;, new Route(&#39;/blog/{slug}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:show&#39;,
)));
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(&#39;blog&#39;, new Route(&#39;/blog&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:index&#39;,
)));
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(&#39;blog&#39;, new Route(&#39;/blog/{page}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:index&#39;,
)));
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(&#39;blog&#39;, new Route(&#39;/blog/{page}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:index&#39;,
  &#39;page&#39; => 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(&#39;blog&#39;, new Route(&#39;/blog/{page}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:index&#39;,
  &#39;page&#39; => 1,
)));
$collection->add(&#39;blog_show&#39;, new Route(&#39;/blog/{show}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:show&#39;,
)));
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(&#39;blog&#39;, new Route(&#39;/blog/{page}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:index&#39;,
  &#39;page&#39; => 1,
), array(
  &#39;page&#39; => &#39;\d+&#39;,
)));
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(&#39;homepage&#39;, new Route(&#39;/{culture}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeDemoBundle:Main:homepage&#39;,
  &#39;culture&#39; => &#39;en&#39;,
), array(
  &#39;culture&#39; => &#39;en|fr&#39;,
)));
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(&#39;contact&#39;, new Route(&#39;/contact&#39;, array(
  &#39;_controller&#39; => &#39;AcmeDemoBundle:Main:contact&#39;,
), array(
  &#39;_method&#39; => &#39;GET&#39;,
)));
$collection->add(&#39;contact_process&#39;, new Route(&#39;/contact&#39;, array(
  &#39;_controller&#39; => &#39;AcmeDemoBundle:Main:contactProcess&#39;,
), array(
  &#39;_method&#39; => &#39;POST&#39;,
)));
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(&#39;homepage&#39;, new Route(&#39;/articles/{culture}/{year}/{title}.{_format}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeDemoBundle:Article:show&#39;,
  &#39;_format&#39; => &#39;html&#39;,
), array(
  &#39;culture&#39; => &#39;en|fr&#39;,
  &#39;_format&#39; => &#39;html|rss&#39;,
  &#39;year&#39; => &#39;\d+&#39;,
)));
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(&#39;acme_hello&#39;, new Route(&#39;/hello/{name}&#39;, array(
  &#39;_controller&#39; => &#39;AcmeHelloBundle:Hello:index&#39;,
)));
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"), &#39;/admin&#39;);
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(&#39;/blog/my-blog-post&#39;);
// array(&#39;slug&#39; => &#39;my-blog-post&#39;, &#39;_controller&#39; => &#39;AcmeBlogBundle:Blog:show&#39;)
$uri = $router->generate(&#39;blog_show&#39;, array(&#39;slug&#39; => &#39;my-blog-post&#39;));
// /blog/my-blog-post

要生成一个URL,你需要指定路由的名称(比如 blog_show)和任意的通配符(比如:slug=my-blog-post)作为参数。通过这些信息,可以生成任意的URL。

class MainController extends Controller
{
  public function showAction($slug)
  {
   // ...
   $url = $this->get(&#39;router&#39;)->generate(&#39;blog_show&#39;, array(&#39;slug&#39; => &#39;my-blog-post&#39;));
  }
}

那么如何从模板内部来生成URL呢?如果你的应用程序前端使用了AJAX请求,你也许想能够基于你的路由配置在javascript中生成URL,通过使用

FOSJsRoutingBundle(https://github.com/FriendsOfSymfony/FOSJsRoutingBundle) 你可以做到:

var url = Routing.generate(&#39;blog_show&#39;, { "slug": &#39;my-blog-post&#39;});

生成绝对路径的URL

默认的情况下,路由器生成相对路径的URL(比如 /blog).要生成一个绝对路径的URL,只需要传入一个true到generate方法作为第三个参数值即可。

$router->generate(&#39;blog_show&#39;, array(&#39;slug&#39; => &#39;my-blog-post&#39;), true);
// http://www.example.com/blog/my-blog-post

当生成一个绝对路径URL时主机是当前请求对象的主机,这个是基于PHP提供的服务器信息自动决定的。当你需要为运行子命令行的脚本生成一个绝对URL时,你需要在Request对象上手动设置期望的主机头。

$request->headers->set(&#39;HOST&#39;, &#39;www.example.com&#39;);

生成带有查询字符串的URL

generate()带有一个数组通配符值来生成URI。 但是如果你传入额外的值,它将被添加到URI作为查询字符串:

$router->generate(&#39;blog&#39;, array(&#39;page&#39; => 2, &#39;category&#39; => &#39;Symfony&#39;));
// /blog/2?category=Symfony

从模板中生成URL

最常用到生成URL的地方是从模板中链接两个页面时,这来需要使用一个模板帮助函数:

Twig格式:

<a href="{{ path(&#39;blog_show&#39;, { &#39;slug&#39;: &#39;my-blog-post&#39; }) }}">
 Read this blog post.
</a>

PHP格式:

<a href="<?php echo $view[&#39;router&#39;]->generate(&#39;blog_show&#39;, array(&#39;slug&#39; => &#39;my-blog-post&#39;)) ?>">
  Read this blog post.
</a>

也可以生成绝对路径:

Twig格式:

<a href="{{ url(&#39;blog_show&#39;, { &#39;slug&#39;: &#39;my-blog-post&#39; }) }}">
 Read this blog post.
</a>

PHP格式:

<a href="<?php echo $view[&#39;router&#39;]->generate(&#39;blog_show&#39;, array(&#39;slug&#39; => &#39;my-blog-post&#39;), 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(&#39;secure&#39;, new Route(&#39;/secure&#39;, array(
  &#39;_controller&#39; => &#39;AcmeDemoBundle:Main:secure&#39;,
), array(
  &#39;_scheme&#39; => &#39;https&#39;,
)));
return $collection;

上面的路由定义就是强迫secure路由使用HTTPS协议访问。

反之,当生成secure 的URL的时候,路由系统会根据当前的访问协议方案生成相应的访问协议。比如当前是HTTP,则会自动生成HTTPS访问;如果是HTTPS访问,那么就也会相应的生成HTTPS访问。

# 如果方案是 HTTPS
{{ path(&#39;secure&#39;) }}
# 生成 /secure
# 如果方案是 HTTP
{{ path(&#39;secure&#39;) }}
# 生成 https://example.com/secure

当然你也可以通过设置_scheme为HTTP,来强制使用HTTP访问协议。除了上面说的强迫使用HTTPS协议访问的设置方法外,还有一种用于站点区域设置

使用requires_channel 比如你想让你站点中/admin 下面的所有路由都必须使用HTTPS协议访问,或者你的安全路由定义在第三方bundle时使用。

总结:

路由系统是一个为将接收的请求URL映射到被调用来处理该请求的controller函数的系统。它既能够让你生成漂亮的URL同时又能保持你的应用程序功能跟这些URL解耦。路由系统是双向机制的,也就是说它们也可以用来生成URL。

相关推荐:

详解Symfony模板快捷变量的用法

详解Symfony在模板和行为中取得request参数的方法

详解symfony如何使用命令创建项目

以上是詳解Symfony2的系統路由的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
PHP依賴注入容器:快速啟動PHP依賴注入容器:快速啟動May 13, 2025 am 12:11 AM

aphpdepentioncontiveContainerIsatoolThatManagesClassDeptions,增強codemodocultion,可驗證性和Maintainability.itactsasaceCentralHubForeatingingIndections,因此reducingTightCightTightCoupOulplingIndeSingantInting。

PHP中的依賴注入與服務定位器PHP中的依賴注入與服務定位器May 13, 2025 am 12:10 AM

選擇DependencyInjection(DI)用於大型應用,ServiceLocator適合小型項目或原型。 1)DI通過構造函數注入依賴,提高代碼的測試性和模塊化。 2)ServiceLocator通過中心註冊獲取服務,方便但可能導致代碼耦合度增加。

PHP性能優化策略。PHP性能優化策略。May 13, 2025 am 12:06 AM

phpapplicationscanbeoptimizedForsPeedAndeffificeby:1)啟用cacheInphp.ini,2)使用preparedStatatementSwithPdoforDatabasequesies,3)3)替換loopswitharray_filtaray_filteraray_maparray_mapfordataprocrocessing,4)conformentnginxasaseproxy,5)

PHP電子郵件驗證:確保正確發送電子郵件PHP電子郵件驗證:確保正確發送電子郵件May 13, 2025 am 12:06 AM

phpemailvalidation invoLvesthreesteps:1)格式化進行regulareXpressecthemailFormat; 2)dnsvalidationtoshethedomainhasavalidmxrecord; 3)

如何使PHP應用程序更快如何使PHP應用程序更快May 12, 2025 am 12:12 AM

tomakephpapplicationsfaster,關注台詞:1)useopcodeCachingLikeLikeLikeLikeLikePachetoStorePreciledScompiledScriptbyTecode.2)MinimimiedAtabaseSqueriSegrieSqueriSegeriSybysequeryCachingandeffeftExting.3)Leveragephp7 leveragephp7 leveragephp7 leveragephpphp7功能forbettercodeefficy.4)

PHP性能優化清單:立即提高速度PHP性能優化清單:立即提高速度May 12, 2025 am 12:07 AM

到ImprovephPapplicationspeed,關注台詞:1)啟用opcodeCachingwithapCutoredUcescriptexecutiontime.2)實現databasequerycachingingusingpdotominiminimizedatabasehits.3)usehttp/2tomultiplexrequlexrequestsandreduceconnection.4 limitesclection.4.4

PHP依賴注入:提高代碼可檢驗性PHP依賴注入:提高代碼可檢驗性May 12, 2025 am 12:03 AM

依赖注入(DI)通过显式传递依赖关系,显著提升了PHP代码的可测试性。1)DI解耦类与具体实现,使测试和维护更灵活。2)三种类型中,构造函数注入明确表达依赖,保持状态一致。3)使用DI容器管理复杂依赖,提升代码质量和开发效率。

PHP性能優化:數據庫查詢優化PHP性能優化:數據庫查詢優化May 12, 2025 am 12:02 AM

DatabasequeryoptimizationinPHPinvolvesseveralstrategiestoenhanceperformance.1)Selectonlynecessarycolumnstoreducedatatransfer.2)Useindexingtospeedupdataretrieval.3)Implementquerycachingtostoreresultsoffrequentqueries.4)Utilizepreparedstatementsforeffi

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境