2

前の質問からの続き:カスタム リチウム ルーティング シナリオ

注: これはLithium フレームワークに固有のものです。

問題

ページ、アイテム、およびカテゴリを区別する規則がまったくない URL スキームを継承しました。これで、キャッチオール コントローラーに渡される非常に一般的なルーターができました。

このキャッチオール コントローラー (PagesController) は、url をキーとして使用して、データベースからページ タイプを取得します。次に、PagesController はメソッドを実行し、ページ タイプに基づいてテンプレートを選択します。この情報は無期限に Memcached に保存されるため、検索は非常に高速です。

しかし、より多くのページ タイプが登場するにつれて、このコントローラーが肥大化しすぎて柔軟性がなくなることがわかります。理想的には、さまざまなページ タイプを独自のコントローラーに分割したいと考えています。

ソリューション?

データベースをチェックして正しいコントローラを決定するルーティング シナリオを作成することは可能でしょうか?

私が最初に考えたのは、 andlithium\net\http\Routerでカスタム ロジックをサブクラス化して使用することです。Router::connect()Router::_parseController()

lithium\net\http\Routebootstrap\routes.php でデータベースにクエリを実行し、結果に基づいて新しいオブジェクトを作成できるとよいでしょう。次に、これを に渡すだけRouter::connect()です。これはひどいハックのようです。

いずれにせよ、Router::connect()そのデザインはそれほど動的であることを意図していません。

4

2 に答える 2

3

さまざまなページ タイプの例や他の URL の例を見ないと、非常に具体的に言うのは難しいですが (前の質問は見ましたが、全体像を把握できていないように感じます)、前の質問と同様に、答えは再びハンドラーを使用したカスタムルーティングになるようです。

Router::connect('/{:pageType}/{:pageKey}', ['pageKey' => null], function($req) {
    $types = ['list', 'of', 'page', 'types'];
    $controller = 'pages';
    $action = 'view';

    if (in_array($req->pageType, $types)) {
        // It's a proper type, do a database lookup and set
        // `$controller` accordingly

        // Here I'm assuming category vs. item view for the action:
        $action = $req->pageKey ? 'view' : 'index';
    } elseif (!$req->pageKey) {
        // It's a `/custom` URL, figure out what to do with it
    }

    // This lets you return custom, arbitrary parameters that Lithium
    // will use for dispatch
    return compact('controller', 'action') + $req->params;
});

ご覧のとおり、ハンドラーを使用すると、ほとんど何でも実行できます。パラメータを解析し、データベース呼び出しを実行し、Lithium がディスパッチするルーティング パラメータの完全に任意のセットを返します。

上記に追加したい唯一のものは、ルールが複雑になり始めた場合に、ページ タイプ/カスタム ページ間のペアリングとルーティング パラメータを管理できる別のクラスです。

于 2013-01-29T16:44:38.320 に答える
-1

フィルターのスタックのように機能するルーターを構築できます。

リストの一番上から始めて、各フィルターに特定の URL と一致するかどうかを尋ねます。一致しない場合は、スタックのずっと下の次のフィルターなどに進みます。

スタックの一番上にあるフィルタほど優先度が高くなります。優先度は、一致するルールまたは単にパフォーマンスが原因である可能性があります。すなわち。データベースの検索は遅いため、一致しない URL をできるだけ早く拒否するプレフィルターを追加します。

フィルターを追加できる非常に一般的な Router クラスを構築できます。ルーターは、特定の入力データ セットで実行を開始するメソッドを備えたフィルター (のスタック) の単なるコンテナーです。

class Router {
    public function addFilter(Filter $filter) {}
    public function run($input) {}  // returns a route
}

interface Filter {
    public function findRoute($input) {} // returns false or a route
}

これにより、非常にモジュール化された構造が可能になります。モジュールが読み込まれると、フィルターを動的に追加できます。

フィルタの例は次のとおりです。

class NewsFilter implements Filter {
    public function findRoute($input) {
        if (preg_match(":^/news/item/([0-9]+)$:", $input["url"], $matches)) {
            $item = $this->news->findItem($matches[1]);
            if (false === $item) {
                return false;
            } else {
                return new NewsRoute($item);
            }
        }
        return false;
    }
}

$router = new Router();
$newsfilter = new NewsFilter();
$router->addFilter($newsfilter);
...
$router->run($input);
于 2013-01-28T17:17:03.147 に答える