# Zend_Controller_Router_Route(日本語)

`Zend_Controller_Router_Route` はフレームワークの標準のルートです。 簡単に利用でき、柔軟なルート定義が可能です。各ルートには、まず (静的および動的な) URL のマッピングが含まれ、 そしてデフォルト値および変数についての制限を指定して初期化します。

とある架空のアプリケーションで、コンテンツの作者情報のページが必要になったとしましょう。 ブラウザで `http://domain.com/author/martel` にアクセスした際に、"martel" とかいう人についての情報を見たいわけです。 この機能を実現するためのルートは、次のようになります。

    $route = new Zend_Controller_Router_Route(
        'author/:username',
        array(
            'controller' => 'profile',
            'action'     => 'userinfo'
        )
    );

    $router->addRoute('user', $route);

`Zend_Controller_Router_Route` のコンストラクタの最初のパラメータは、ルートの定義です。 これを URL にマッチさせます。ルート定義は静的な部分と動的な部分で構成され、 それをスラッシュ ('/') で連結します。 静的な部分は単なるテキスト (例. `author`) です。 動的な部分を変数と呼び、変数名の前にコロンをつけて (例. `:username`) 表します。

## 文字の使用法

現在の実装では、(スラッシュ以外の) 任意の文字を変数名として使用できます。しかし、 PHP の変数名として使用できる文字だけを用いることを強く推奨します。 このようにしておくことで、 将来実装が変更されたときにバグを引き起こす可能性を抑えられます。

この例のルートは、ブラウザで `'http://domain.com/author/martel'` を指した際にマッチします。 この場合、すべての変数の値が `Zend_Controller_Request` オブジェクトに注入され、`ProfileController` からアクセスできるようになります。 この例が返す変数は、以下のようなキーと値のペアを持つ配列となります。

    $values = array(
        'username'   => 'martel',
        'controller' => 'profile',
        'action'     => 'userinfo'
    );

その後、`Zend_Controller_Dispatcher` は (デフォルトモジュールの) `ProfileController` クラスにある `userinfoAction()` メソッドを実行します。変数にアクセスするには、 `Zend_Controller_Action::_getParam()` あるいは `Zend_Controller_Request::getParam()` メソッドを使用します。

    public function userinfoAction()
    {
        $request = $this->getRequest();
        $username = $request->getParam('username');

        $username = $this->_getParam('username');
    }

ルート定義には、特殊文字 (ワイルドカード) を含めることができます。これは '*' 記号で表します。 これを使用して、Module ルートと同様にパラメータを扱う (変数名 => 値 のペアを URI で定義する) ことができます。 次のルートは、Module ルートの挙動をまねたものです。

    $route = new Zend_Controller_Router_Route(
        ':module/:controller/:action/*',
        array('module' => 'default')
    );
    $router->addRoute('default', $route);

## 変数のデフォルト

ルートで使用するすべての変数についてデフォルト値を指定できます。 これは、 `Zend_Controller_Router_Route` のコンストラクタの 2 番目のパラメータで指定します。 このパラメータは、変数名をキーとする配列で、 対応する値にそのデフォルト値を指定します。

    $route = new Zend_Controller_Router_Route(
        'archive/:year',
        array('year' => 2006)
    );
    $router->addRoute('archive', $route);

上のルートは `'http://domain.com/archive/2005'` および `'http://example.com/archive'` のような URL にマッチします。後者の場合、変数 year にはデフォルト値である 2006 が設定されます。

この例は、year 変数をリクエストオブジェクトに注入することになります。 そしてルーティング情報が存在しない (コントローラやアクションのパラメータが定義されていない) ので、 アプリケーションはデフォルトのコントローラのデフォルトアクションメソッド (ともに `Zend_Controller_Dispatcher_Abstract` で定義されています) にディスパッチします。より使いやすくするには、 ルートのデフォルトとしてコントローラとアクションを定義しておく必要があります。

    $route = new Zend_Controller_Router_Route(
        'archive/:year',
        array(
            'year'       => 2006,
            'controller' => 'archive',
            'action'     => 'show'
        )
    );
    $router->addRoute('archive', $route);

このルートは、`ArchiveController` の `showAction()` を実行します。

## 変数の制約

`Zend_Controller_Router_Route` のコンストラクタの 三番目のパラメータで、変数の制約を指定できます。 これは、正規表現で指定します。

    $route = new Zend_Controller_Router_Route(
        'archive/:year',
        array(
            'year'       => 2006,
            'controller' => 'archive',
            'action'     => 'show'
        ),
        array('year' => '\d+')
    );
    $router->addRoute('archive', $route);

上の例のルートでは、year 変数の値が数値データである場合にのみ Rewrite ルータにマッチします。つまり `http://domain.com/archive/2345` はマッチしますが `http://example.com/archive/test` はマッチしません。 この場合はチェイン内の次のルートに処理を移します。

## 翻訳済みセグメント

標準のルートは、翻訳済みセグメントをサポートします。この機能を使用するには、 次のいずれかの方法で翻訳器 (`Zend_Translate` のインスタンス) を定義しなければなりません。

- レジストリに、キー `Zend_Translate` で格納する

- 静的メソッド `Zend_Controller_Router_Route::setDefaultTranslator()` で設定する

- コンストラクタの 4 番目のパラメータとして渡す

デフォルトでは、`Zend_Translate` のインスタンスで指定したロケールを使用します。これを上書きするには、 (`Zend_Locale` のインスタンスあるいはロケール文字列で) 次のいずれかの方法で設定します。

- レジストリに、キー `Zend_Locale` で格納する

- 静的メソッド `Zend_Controller_Router_Route::setDefaultLocale()` で設定する

- コンストラクタの 5 番目のパラメータとして渡す

- アセンブルメソッドのパラメータ `@locale` として渡す

翻訳済みセグメントはふたつの部分に分かれます。 固定セグメントの前には @ 記号がひとつつき、 アセンブル時に現在のロケールに翻訳され、 マッチングの際にはメッセージ ID に戻されます。 動的セグメントの前には `:@` がつきます。 アセンブルの際に、指定したパラメータが翻訳され、 パラメータの位置に挿入されます。 マッチングの際には、URL の翻訳済みパラメータが メッセージ ID に戻されます。

### メッセージ ID と分割された言語ファイル

ルートの中で使いたいメッセージ ID が、 ビュースクリプトやその他の部分ですでに使われていることもあるでしょう。 URL の安全性を確保するには、 ルートで使用するメッセージを別の言語ファイルに分割しなければなりません。

標準のルートで翻訳済みセグメントを使用するための準備として もっともシンプルな方法は、次のようになります。

    // 翻訳器を準備します
    $translator = new Zend_Translate(
        array(
            'adapter' => 'array',
            'content' => array(),
            'locale'  => 'en'
        )
    );
    $translator->addTranslation(
        array(
            'content' =>
                array(
                    'archive' => 'archiv',
                    'year'    => 'jahr',
                    'month'   => 'monat',
                    'index'   => 'uebersicht'
                ),
            'locale'  => 'de'
        )
    );

    // 現在のロケールを翻訳器に設定します
    $translator->setLocale('en');

    // ルートのデフォルト翻訳器として設定します
    Zend_Controller_Router_Route::setDefaultTranslator($translator);

これは、静的セグメントを使用する例です。

    // ルートを作成します
    $route = new Zend_Controller_Router_Route(
        '@archive',
        array(
            'controller' => 'archive',
            'action'     => 'index'
        )
    );
    $router->addRoute('archive', $route);

    // URL をデフォルトのロケールでアセンブルします: archive
    $route->assemble(array());

    // URL をドイツ語でアセンブルします: archiv
    $route->assemble(array());

動的セグメントを使用すると、 モジュールルートの翻訳済みバージョンを作ることができます。

    // ルートを作成します
    $route = new Zend_Controller_Router_Route(
        ':@controller/:@action/*',
        array(
            'controller' => 'index',
            'action'     => 'index'
        )
    );
    $router->addRoute('archive', $route);

    // URL をデフォルトのロケールでアセンブルします: archive/index/foo/bar
    $route->assemble(array('controller' => 'archive', 'foo' => 'bar'));

    // URL をドイツ語でアセンブルします: archiv/uebersicht/foo/bar
    $route->assemble(array('controller' => 'archive', 'foo' => 'bar'));

静的セグメントと動的セグメントを同時に使用することもできます。

    // ルートを作成します
    $route = new Zend_Controller_Router_Route(
        '@archive/:@mode/:value',
        array(
            'mode'       => 'year'
            'value'      => 2005,
            'controller' => 'archive',
            'action'     => 'show'
        ),
        array('mode'  => '(month|year)'
              'value' => '\d+')
    );
    $router->addRoute('archive', $route);

    // URL をデフォルトのロケールでアセンブルします: archive/month/5
    $route->assemble(array('mode' => 'month', 'value' => '5'));

    // URL をドイツ語でアセンブルします: archiv/monat/5
    $route->assemble(array('mode' => 'month', 'value' => '5', '@locale' => 'de'));