2

MVCフレームワークでリクエストをディスパッチしようとしています。現在のURIを定義済みのルートと照合するルーティングオブジェクトがあります。一致する場合は、Routeオブジェクトのインスタンスを返します。そのRouteオブジェクトを介して、一致したコントローラー、メソッド、およびメソッドの引数にアクセスできます。

私はそれをこのように使うことができます:

$route->getClass(); name of controller class to instantiate
$route->getMethod(); name of method to call
$route->getArgs(); array holding arguments that should be passed to method

必要に応じて、新しい引数を追加することもできます。たとえば、依存性注入コンテナと現在のHTTPリクエストオブジェクトインスタンスを次のように引数に追加できます。

$route->addArg('container', $container);
$route->addArg('request', $request);

これで、$ route-> getArgsは、URIからフェッチされたすべての引数だけでなく、$containerインスタンスと$requestインスタンスも保持します。$ containerは、私が書いた依存性注入コンテナーです。また、$ requestは、現在のHTTPリクエストを表すオブジェクトです。

つまり、ルーターをインスタンス化し、現在のルートを取得してから、すべてのメソッド/アクションコントローラー内で使用したいオブジェクトを追加するというアイデアです。次に、そのRouteオブジェクトをDispatcherに渡します。リクエストがディスパッチされると、すべてのメソッド/アクションコントローラーで$ container、$ request、およびその他の引数を使用できるようになります。

私が抱えている問題は、使用するときにブログコントローラーとpostメソッドを言うことです。デフォルトでは、常に、$containerと$requestのインスタンスが必要です(Route :: $ argsにプッシュしたため、ルート定義で定義された、またはURIからフェッチされた他の引数/変数。

したがって、Imがブログコントローラーにいるときは、postメソッドを次のように動作させます。

public function post($container, $request)
{
if($request->isAjax) {
// -- Its ajax request
}

$twig = $container->getService("Twig");
}

私は次のようなリクエストをディスパッチします:

それを機能させるためにcall_user_function_arrayを使用しています:

$app = new $controller();
call_user_function_array(array($app, $method), $args);

これですべて正常に機能しますが、問題が1つあります。そのポストコントローラーを使用する場合、ポストメソッド引数の順序に注意する必要があります。

だから私はこれを行うことができます:

public function post($id, $url, $container, $request) {
// -- SNIP --
}

しかし、私はそれをこのように使うことはできません:

public function post($container, $url, $request, $id) {
/-- SNIP --
}

そのため、問題が発生します。メソッド内で引数を希望どおりに混在させることはできません。これらの引数がRoute:$args配列で定義される順序に注意する必要があります。

すべてのメソッド/アクションコントローラーには、$ request、$ containerインスタンスに加えて、URIを介してフェッチされるか、ルート定義で定義される引数が必要です。

postメソッドが引数を取得する順序を考える必要なしにそれを機能させる方法はありますか?これは参照による受け渡しと関係がありますか?phpは変数を値で渡すので?

call_user_function_arrayを使用していて、call_user_function_arrayの解決策を見つけたいと思っています。これは可能ですか?

そうでない場合、これはReflectionクラスを使用して実行できますか?

4

2 に答える 2

2

これが私の問題の解決策です。

だから、私はリクエストをディスパッチするために必要なすべてを持っています:

$class = "\\Application\\Controller\\Blog";
$method = "post";
$args = array('id' => 1, 'url' => 'some-url', 'container' => DICOBJ, 'request' => RQSTOBJ);

次に、そのリクエストをディスパッチする必要があります。これにより、ユーザーは必要に応じて任意の順序で引数を挿入できます。

これが行われるべきことです:

$app = new $class();

$rm = new \ReflectionMethod($app, $method);
$params = $rm->getParameters();

$argsOrdered = array();
foreach($params as $param) {
    $argsOrdered[$param->getName()] = $args[$param->getName()];
}

call_user_func_array(array($app, $method), $argsOrdered);

タダァー!!!

つまり、これはユーザーによって定義された引数を取得し、ユーザーがそれらを書き込んだ順序でそれらを配列として返します。次に、ユーザーが望む引数のみを保持する別の$ argsOrdered配列を作成し、ユーザーが望む方法で順序付けします:)

ReflectionMethodを使用してメソッドを検査しています。そして最後にcall_user_func_arrayでリクエストをディスパッチしますが、Reflectionクラスを使用してコントローラーインスタンスを取得することもできます。

それでおしまい。このソリューションはエレガントだと思いますか?これはもっと速くできますか?

于 2012-10-19T21:23:39.283 に答える
1

Reflectionクラスを使用すると、呼び出したい関数の各パラメーターの引数名を取得できます。これにより、引数が正しい順序になっているかどうかを非常に簡単に確認できます。だけでそれを行うことはできませんcall_user_function_array

特に、getParameters() methodReflectionMethodクラスでを使用できます。

そこから、あなたは何をすべきかを知っていると思います(渡された引数のキーでパラメータ配列の各キーをチェックしてください)。

于 2012-10-19T15:13:08.420 に答える