ルーター

ルーターはWebやコンソールなどの外部コンテキストのリソースリクエストを、BEAR.Sunday内部のリソースリクエストに変換します。

$request = $app->router->match($GLOBALS, $_SERVER);
echo (string) $request;
// get page://self/user?name=bear

Webルーター

デフォルトのWebルーターではHTTPリクエストのパス($_SERVER['REQUEST_URI'])に対応したリソースクラスにアクセスされます。 例えば/indexのリクエストは{Vendor名}\{Project名}\Resource\Page\IndexクラスのHTTPメソッドに応じたPHPメソッドにアクセスされます。

Webルーターは規約ベースのルーターです。設定やスクリプトは必要ありません。

namespace MyVendor\MyProject\Resource\Page;

// page://self/index
class Index extends ResourceObject
{
    public function onGet(): static // GETリクエスト
    {
    }
}

CLIルーター

cliコンテキストではコンソールからの引数が外部入力になります。

php bin/page.php get /

BEAR.SundayアプリケーションはWebとCLIの双方で動作します。

複数の単語を使ったURI

ハイフンを使い複数の単語を使ったURIのパスはキャメルケースのクラス名を使います。 例えば/wild-animalのリクエストはWildAnimalクラスにアクセスされます。

パラメーター

HTTPメソッドに対応して実行されるPHPメソッドの名前と渡される値は以下の通りです。

HTTPメソッド PHPメソッド  渡される値
GET onGet $_GET
POST onPost $_POST または 標準入力
PUT onPut ※標準入力
PATCH onPatch ※標準入力
DELETE onDelete ※標準入力 

リクエストのメディアタイプは以下の2つが利用できます。

  • application/x-www-form-urlencoded // param1=one&param2=two
  • application/json // {“param1”: “one”, “param2”: “one”} (POSTの時は標準入力の値が使われます)

PHPマニュアルのPUT メソッドのサポートもご覧ください。

メソッドオーバーライド

HTTP PUT トラフィックや HTTP DELETE トラフィックを許可しないファイアウォールがあります。 この制約に対応するため、次の2つの方法でこれらの要求を送ることができます。

  • X-HTTP-Method-Override POSTリクエストのヘッダーフィールドを使用してPUTリクエストやDELETEリクエストを送る。
  • _method URI パラメーターを使用する。例)POST /users?…&_method=PUT

Auraルーター

リクエストのパスをパラメーターとして受け取る場合はAura Routerを使用します。

composer require bear/aura-router-module ^2.0

ルータースクリプトのパスを指定してAuraRouterModuleをインストールします。

use BEAR\Package\AbstractAppModule;
use BEAR\Package\Provide\Router\AuraRouterModule;

class AppModule extends AbstractAppModule
{
    protected function configure()
    {
        // ...
        $this->install(new AuraRouterModule($appDir . '/var/conf/aura.route.php'));
    }
}

キャッシュされているDIファイルを消去します。

rm -rf var/tmp/*

ルータースクリプト

ルータースクリプトではグローバルで渡されたMapオブジェクトに対してルートを設定します。 ルーティングにメソッドを指定する必要はありません。1つ目の引数はルート名としてパス、2つ目の引数に名前付きトークンのプレイスフォルダーを含んだパスを指定します。

var/conf/aura.route.php

<?php
/* @var \Aura\Router\Map $map */
$map->route('/blog', '/blog/{id}');
$map->route('/blog/comment', '/blog/{id}/comment');
$map->route('/user', '/user/{name}')->tokens(['name' => '[a-z]+']);
  • 最初の行では/blog/bearとアクセスがあるとpage://self/blog?id=bearとしてアクセスされます。 (=BlogクラスのonGet($id)メソッドに$id=bearの値でコールされます。)

  • /blog/{id}/commentBlog\Commentクラスにルートされます。

  • token()はパラメーターを正規表現で制限するときに使用します。

優先ルーター

Auraルーターでルートされない場合は、Webルーターが使われます。 つまりパスでパラメーターを渡すURIだけにルータースクリプトを用意すればOKです。

パラメーター

パスからパラメーターを取得するためにAuraルーターは様々な方法が用意されています。

カスタムマッチング

下のスクリプトは{date}が適切なフォーマットの時だけルートします。

$map->route('/calendar/from', '/calendar/from/{date}')
    ->tokens([
        'date' => function ($date, $route, $request) {
            try {
                new \DateTime($date);
                return true;
            } catch(\Exception $e) {
                return false;
            }
        }
    ]);

オプション

オプションのパラメーターを指定するためにはパスに{/attribute1,attribute2,attribute3}の表記を加えます。

例)

$map->route('archive', '/archive{/year,month,day}')
    ->tokens([
        'year' => '\d{4}',
        'month' => '\d{2}',
        'day' => '\d{2}',
    ]);

プレイスホルダーの内側に最初のスラッシュがあるのに注意してください。 そうすると下のパスは全て’archive’にルートされパラメーターの値が付加されます。

  • /archive : ['year' => null, 'month' => null, 'day' = null]
  • /archive/1979 : ['year' => '1979', 'month' => null, 'day' = null]
  • /archive/1979/11 : ['year' => '1979', 'month' => '11', 'day' = null]
  • /archive/1979/11/07 : ['year' => '1979', 'month' => '11', 'day' = '07']

オプションパラメーターは並ぶ順にオプションです。つまり”month”なしで”day”を指定することはできません。

ワイルドカード

任意の長さのパスの末尾パラメーターとして格納したいときにはwildcard()メソッドを使います。

$map->route('wild', '/wild')
    ->wildcard('card');

スラッシュで区切られたパスの値が配列になりwildcard()で指定したパラメーターに格納されます。

  • /wild : ['card' => []]
  • /wild/foo : ['card' => ['foo']]
  • /wild/foo/bar : ['card' => ['foo', 'bar']]
  • /wild/foo/bar/baz : ['card' => ['foo', 'bar', 'baz']]

その他の高度なルートに関してはAura Routerのdefining-routesをご覧ください。

リバースルーティング

ルートの名前とパラメーターの値からURIを生成することができます。

use BEAR\Sunday\Extension\Router\RouterInterface;

class Index extends ResourceObject
{
    /**
     * @var RouterInterface
     */
    private $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    public function onGet(): static
    {
        $userLink = $this->router->generate('/user', ['name' => 'bear']);
        // '/user/bear'

リクエストメソッド

リクエストメソッドを指定する必要はありません。

リクエストヘッダー

通常リクエストヘッダーはAura.Routerに渡されていませんが RequestHeaderModuleをインストールするとAura.Routerでヘッダーを使ったマッチングが可能になります。

$this->install(new RequestHeaderModule());

独自のルーターコンポーネント