0

現在、ルート定義として次のような一連のページがあります。

$app->get('/{region}/{instance}/events', 'MyApp\EventsController::index');
$app->post('/{region}/{instance}/events', 'MyApp\EventsController::add');
$app->get('/{region}/{instance}/event/{id}', 'MyApp\EventsController::edit');
$app->post('/{region}/{instance}/event/{id}', 'MyApp\EventsController::update');

次に、4 つのすべての関数 ( 、、、および) のパラメーターとしてandEventsControllerを持たなければならないクラスがあります。それをクリーンアップして、との値をグローバルオブジェクトに移動できるかどうか疑問に思っています。regioninstanceindexaddeditupdateregioninstance$app

できるようになりたいです

$app->mount('/{region}/{instance}/', new MyApp\EventsControllerProvider());

そして、変数と変数をEventsControllerProvider検証し、そのパスの上に「イベント」ルートをマップしますが、マウントポイントに変数を含めることはできないようです (メソッドは追加のパラメーターを許可しません)。regioninstanceControllerProviderInterface::connect()

これを行うためのきれいな方法はありますか?私はこの方法を考えましたが、これは他のルーティングメカニズムに反するようです:

$app->get('/{region}/{instance}/{action}' function($region, $instance, $action) use ($app) {

  if ($app['myapp.valid-region']($region) === false) return $app->abort(404);
  if ($app['myapp.valid-instance']($instance) === false) return $app->abort(404);


  switch ($action) {
    case 'events':
      $c = new MyApp\EventsController();
      return $c->index();
  }
});
4

3 に答える 3

2

数年後、私は解決策を見つけました。当時は無かったかもしれませんが、今はあります。元の質問で述べたように、 にControllerProviderは役立つ追加パラメーターはありませんが、ミドルウェアでこの問題を解決できます。

$app->mount('/{region}/{instance}/', new MyApp\EventsControllerProvider())
->before(function(Request $r, Application $a) {
  $region = $r->attributes->get('region');
  $instance = $r->attributes->get('instance');
  $regionInfo = $a['myRegionService']($region, $instance);
  if ($regionInfo === false) {
    return $a->abort(404, 'No such region');
  }
  $a['currentRegionInfo'] = $regionInfo;
});

これで、コントローラーの下にマウントされたコントローラーEventsControllerProviderは、リージョン/インスタンスで検証を行う必要がなくなりました。これは、事前に行われているためです (問題がある場合は 404 が返されます)。$a['currentRegionInfo']コントローラが現在のリージョンを知る必要がある場合は、すでに設定されているため、 から引き出すことができます。このミドルウェアは、この特定のルート コレクションにのみバインドされるため、アプリケーションで定義された他のルートに対しては呼び出されません。

URL で定義された変数は、そのパラメーターのRequest下のオブジェクトで公開されます。attributes技術的には、いずれのコントローラもメソッドに渡されたregionおよびパラメータを引き続き取得できますが、現在はその必要はありません。instance

于 2016-02-07T06:13:21.460 に答える
0

それはあなたの問題とまったく同じではありませんが、次の形式のリソースとサブリソースを持つ API に少し似たものが必要でした:

/resources/{resource_id}/subresources/{subresource_id}

さまざまなサブリソースが可能です。

最初にリソースとの照合を終了し、次にサブリソースの新しいリクエストを作成し、resource_id をクエリ パラメータとして使用しました。

私はそれが理想的で非常にきれいだとは思いませんが、うまくいきます(今のところ):

$app->mount('/subresource/1', new Subresource1ControllerProvider());
// etc for subresource 2/3/n

$app->match('/resources/{resource_id}/{slug}', function (Request $request, $resource_id, $slug) use ($app)
{
    $currentQueryParams = $request->getQueryString();
    $newQueryParams = '?resource_id=' . $resource_id .
        ((empty($currentQueryParams)) ? '' : '&' . $currentQueryParams);

    $subRequest = Request::create('/' . $slug . $newQueryParams, $request->getMethod(), $request->request->all(),
                        $request->cookies->all(), array(), $request->server->all(), $request->getContent());

    if ($request->getSession()) { $subRequest->setSession($request->getSession()); }

    return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
})
->assert('slug', '.*');

そして、私のコントローラープロバイダーで:

class Subresource1ControllerProvider implements ControllerProviderInterface
{
    public function connect(Application $app)
    {
        $controllers = $app['controllers_factory'];

        $controllers->get('/', function (Request $request) use ($app) {

            $app['resource.id'] = $request->query->get('resource_id');
            $resource = $app['resource'];

            // do your thing ...

            return /* whatever */
        });

        return $controllers;
    }
}

欠点は、/subresource/{subresource_id} にも直接アクセスできるようになることです。

于 2013-10-01T08:38:29.843 に答える