BEAR.Sunday

BEAR.SundayのRouterCollection

More than 3 years have passed since last update.

RouterCollection

BEAR.Packageやデモで使用されているのデフォルトのルーターは WebRouter というURLそのままページリソースのパスにマッピングするルーターです。
ルーティングを変更したい場合は、これを別のルーターに差し替えて使用できます。

ここまでは普通なのですが、RouterCollectionというルーターを 組み合わせて 使う面白い仕組みがあります。

サンプル

今回は BEAR.DemoAppsのハローワールドサンプルのルーティング設定を追加してみます。

name=xxx というクエリの部分を変更してみます。

スクリーンショット 2014-12-08 21.46.34.png

今回のサンプルはgithubに置いておきます。
zukimochi/BEAR.DemoApps at feature/router-collection

タスク

以下の手順で作成します。

  1. ルーターのプロバイダーを作成
  2. ルーターコレクションのプロバイダーを作成
  3. DI

以上です。

ルーターのプロバイダーを作成

今回はWebRouterにAura.Routerを組み合わせたRouterCollectionを作成することにします。
まず、ルーティングを設定したAura.Routerを生成するプロバイダー作ります。

<?php

namespace Demo\Sandbox\Provide\Router\Adapter;

use Aura\Router\Router;
use BEAR\Package\Provide\Router\Adapter\AuraRouter;
use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;
use Ray\Di\ProviderInterface;

class AuraRouterProvider implements ProviderInterface
{
    /**
     * @var \Aura\Router\Router
     */
    private $router;

    /**
     * @param Router $router
     *
     * @Inject
     */
    public function __construct(Router $router)
    {
        $this->router = $router;
    }

    /**
     * @return AuraRouter
     */
    public function get()
    {
        $this->addHelloRoutes();
        $auraRouter = new AuraRouter($this->router);

        return $auraRouter;
    }

    /**
     * @return void
     */
    public function addHelloRoutes()
    {
        $this->router->add(null, '/hello/world/{name}')
            ->addTokens(['name' => '[a-zA-Z]+'])
            ->addValues(['path' => '/hello/world']);
    }
}

ちょっとややこしいのはAuraRouterはBEAR.Packageが用意しているAura.Routerのアダプターで、Routerがルータークラスです。

ルーターコレクションのプロバイダーを作成

<?php

namespace Demo\Sandbox\Provide\Router\Adapter;

use BEAR\Package\Provide\Router\Adapter\AdapterInterface;
use BEAR\Package\Provide\Router\Adapter\RouterCollection;
use Ray\Di\Di\Inject;
use Ray\Di\Di\Named;
use Ray\Di\ProviderInterface;

class RouterCollectionProvider implements ProviderInterface
{
    /**
     * @var \BEAR\Package\Provide\Router\Adapter\AdapterInterface
     */
    private $auraRouter;

    /**
     * @var \BEAR\Package\Provide\Router\Adapter\AdapterInterface
     */
    private $webRouter;

    /**
     * @param AdapterInterface $auraRouter
     * @param AdapterInterface $webRouter
     *
     * @Inject
     * @Named("auraRouter=aura_router,webRouter=web_router")
     */
    public function __construct(AdapterInterface $auraRouter, AdapterInterface $webRouter)
    {
        $this->auraRouter = $auraRouter;
        $this->webRouter = $webRouter;
    }

    /**
     * @return RouterCollection
     */
    public function get()
    {
        $routers =  [$this->auraRouter, $this->webRouter];
        $routerCollection = new RouterCollection($routers);

        return $routerCollection;
    }
}

ルーターコレクションはルーターの配列を受け取り、配列の順番でマッチングをかけてマッチした時点で処理を止めて対象のパスやクエリを返します。
今回はAura.Router、WebRouterの順でマッチングします。

DI

ルーターのDI設定を下記のように記述します。

<?php

namespace Demo\Sandbox\Module;

use Ray\Di\AbstractModule;

class RouterCollectionModule extends AbstractModule
{
    protected function configure()
    {
        $this->bind('BEAR\Sunday\Extension\Router\RouterInterface')
            ->to('BEAR\Package\Provide\Router\Router');
        $this->bind('BEAR\Package\Provide\Router\Adapter\AdapterInterface')
            ->toProvider('Demo\Sandbox\Provide\Router\Adapter\RouterCollectionProvider');
    }
}

これで、ルーターが先ほど作成したルーターコレクションに差し替えられました。
使用者側のコードには一切変更はありません。

確認

これでルーティングの設定は完了です。

スクリーンショット 2014-12-08 22.09.02.png

ほとんどのページがWebRouterのマッチングで問題ないものの、一部分だけ別のルールでルーティングしたい場合にはこういった方法で組み合わせることが出来ます。

組み合わせ

今回はルーターを組み合わせてみました。
この他にログをファイルに書き込むロガーと、DBに書き込むロガーを組み合わせるなど面白い使い方ができます。

特定機能を差し替えるのではなく、組み合わせて使うのが簡単なところもBEAR.Sundayの面白いところだと思います。