web-dev-qa-db-ja.com

Laravel 4で手動でディスパッチしたリクエストのクエリ文字列パラメータにアクセスするにはどうすればよいですか?

私は単純なAPIを作成し、このAPIの上に単純なWebアプリケーションを構築しています。

「自分のAPIを直接消費」したいので、最初にGoogleで検索し、StackOverflowでこの回答を見つけました。これは、最初の質問に完全に答えます。 自分のAPIを消費するLaravel API

これでうまくいきました。次のような操作でAPIにアクセスできます。

_$request = Request::create('/api/cars/'.$id, 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
_

これは素晴らしい!しかし、私のAPIでは、オプションのfieldsパラメーターをGETクエリ文字列に追加して、次のように返される特定の属性を指定することもできます。

_http://cars.com/api/cars/1?fields=id,color
_

これをAPIで実際に処理する方法は、次のようなものです。

_public function show(Car $car)
{
     if(Input::has('fields'))
     {
          //Here I do some logic and basically return only fields requested
          ....
     ...
 }
_

以前のクエリ文字列パラメータなしのアプローチで行ったのと同様のことを、次のように実行できると思います。

_$request = Request::create('/api/cars/' . $id . '?fields=id,color', 'GET');
$instance = json_decode(Route::dispatch($request)->getContent());
_

しかし、そうではないようです。簡単に言うと、コードをステップ実行した後、Requestオブジェクトが正しく作成されているようです(そして、fieldsパラメーターを正しく引き出していますそしてid、colorを割り当てます)、ルートは正常にディスパッチされているようですが、APIコントローラー自体の中でアクセスする方法がわかりませんfieldパラメータ。 Input::get('fields')(「通常の」リクエストに使用するもの)を使用しても何も返されません。これは、静的なInputが最初のリクエストを参照またはスコープしているためです。 、アプリ自体から「手動で」ディスパッチした新しいリクエストではありません。

だから、私の質問は本当に私がこれをどのように行うべきかということです。私は何か間違ったことをしていますか?理想的には、APIコントローラーで醜いことや特別なことをしないようにしたい、内部にディスパッチされたリクエストにInput :: getを使用できるようにし、2回目のチェックなどを行う必要がないようにします。

9
Kevin Mitchell

Inputの使用は、新しく作成されたリクエストではなく、実際には現在のリクエストを参照しているという点で正しいです。入力は、Request::create()でインスタンス化するリクエストインスタンス自体で利用できます。

_Illuminate\Http\Request_を使用してリクエストをインスタンス化していた場合は、$request->input('key')または$request->query('key')を使用してクエリ文字列からパラメータを取得できます。

ここでの問題は、ルートで_Illuminate\Http\Request_インスタンスを使用できない可能性があることです。ここでの解決策(Inputファサードを引き続き使用できるようにするため)は、現在のリクエストの入力を物理的に置き換えてから、元に戻すことです。

_// Store the original input of the request and then replace the input with your request instances input.
$originalInput = Request::input();

Request::replace($request->input());

// Dispatch your request instance with the router.
$response = Route::dispatch($request);

// Replace the input again with the original request input.
Request::replace($originalInput);
_

これは(理論的には)機能するはずであり、内部APIリクエストが行われる前後に元のリクエスト入力を引き続き使用できるはずです。

18
Jason Lewis

私もこの問題に直面していて、ジェイソンの素晴らしい答えのおかげでそれを機能させることができました。

ルートも交換する必要があることがわかったことを付け加えたいと思います。それ以外の場合、Route::currentRouteName()は、スクリプトの後半でディスパッチされたルートを返します。

これについての詳細は私の ブログ投稿 で見つけることができます。

また、スタッキングの問題についていくつかのテストを行い、このアプローチを使用して内部APIメソッドを相互に繰り返し呼び出しました。それはうまくいきました!すべてのリクエストとルートが正しく設定されています。

2
santacruz

内部APIを呼び出し、(クエリ文字列ではなく)配列を介してパラメーターを渡したい場合は、次のように実行できます。

$request = Request::create("/api/cars", "GET", array(
   "id" => $id,
   "fields" => array("id","color")
));
$originalInput = Request::input();//backup original input
Request::replace($request->input());
$car = json_decode(Route::dispatch($request)->getContent());//invoke API
Request::replace($originalInput);//restore orginal input

参照: Laravel:独自のAPIを呼び出す

0
Tho