ホームページ > php教程 > PHP开发 > Symfony2のシステムルーティングの詳細説明 勉強ノート

Symfony2のシステムルーティングの詳細説明 勉強ノート

高洛峰
リリース: 2016-12-26 11:12:46
オリジナル
1122 人が閲覧しました

この記事では、Symfony2 のシステムルーティングについて詳しく説明します。参考として皆さんと共有してください。詳細は次のとおりです:

本格的な Web アプリケーションには美しい URL が必須です。これにより、index.php?article_id=57 などの醜い URL が非表示になり、より人気が高まります。 /read/intro-to-symfony を代替として歓迎します。

柔軟性を持つことがより重要です。ページの URL を変更したい場合、たとえば /blog から /new に変更したい場合はどうすればよいでしょうか?

検索して更新する必要があるリンクはいくつありますか? Symfony のルーターを使用している場合、この変更は簡単です。

Symfony2 ルーターを使用すると、よりクリエイティブな URL を定義でき、アプリケーションのさまざまな領域をマッピングできます。

コントローラーにマッピングされた複雑なルートを作成し、テンプレートとコントローラー内で URL を生成できます

バンドル (または他の場所) からルート リソースをロードします

ルートをデバッグします

ルート アクティビティ

パスは、URL バインディングからのリンクですパターンをコントローラーに送信します。

/blog/my-post や /blog/all-about-symfony のような任意のパスを照合し、ブログ エンティティを検索してレンダリングできるコントローラーにそれらを送信するとします。

パスは非常に単純です:

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 パターンを定義します。 like /blog/* ここでのワイルドカードは slug という名前です。 URL/blog/my-blog-post の場合、slug 変数は値 my-blog-post を取得します。
_controller パラメーターは、URL がこのパスに一致した場合にどのコントローラーが実行されるかを Symfogy に指示する特定のキーです。
_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 コントローラーが実行され、$slug 変数の値が my-post になります

Symfogy2 のルーター ターゲット: 要求された URL をコントローラ。

ルーティング: 内部の秘密

リクエストがアプリケーションに送信されるとき、そのリクエストにはクライアントが取得したいリソースのアドレスが含まれています。このアドレスは URL または URI と呼ばれます。 /contact、/blog/read-me またはその他のスタイルの場合があります。

GET /blog/my-blog-post

Symfony2 ルーティング システムの目標は、これらの URL を解析し、リクエストに応答するためにどのコントローラーを実行するかを決定することです。

ルーティングプロセス全体は次のように分割できます:

1. リクエストは Symfony2 のフロントエンドコントローラー (app.php) によって処理されます。
2.Symfony2 コア (カーネル) はルーターにリクエストを確認するように依頼します。
3. ルーターは、受信した URL を特定のパスと照合し、実行する必要があるコントローラーなどの関連情報を返します。
4.Symfony2 コアはコントローラーを実行し、最終的に Response オブジェクトを返します。

ルーター層は受信したURLを特定のコントローラーに変換して実行するツールです。

ルートの作成

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;),
));
ログイン後にコピー

基本的なルーティング構成

ルートの定義は簡単です。通常、アプリケーションには多くのルーティングがあります。 。基本ルートは、パターン部分とデフォルト配列部分の 2 つの部分で構成されます。

例:

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: ホームページ コントローラーに。 _controller 文字列は、Symfony2 によって対応する PHP 関数に変換され、実行されます。

プレースホルダーを使用したルーティング

もちろん、ルーティング システムは、より興味深いルートをサポートしています。多くのルートには、1 つ以上の名前付きワイルドカード プレースホルダーが含まれています。

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;
ログイン後にコピー

このパターンは、形。プレースホルダー {slug} に一致する値がコントローラーで使用されます。つまり、URL が /blog/hello-world の場合、$slug 変数の値は hello-world となり、この値はコントローラーで使用可能になります。デフォルトではすべてのプレースホルダーが必須であるため、このパターンは /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 にブログの 2 ページ目を表示させる場合は、新しい {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框架的PHP程序设计有所帮助。

更多Symfony2学习笔记之系统路由详解相关文章请关注PHP中文网!

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート