2016-11-23 3 views
5

facebook batch requests関数の動作をグラフのAPIに再現しようとしています。 Symfonyのバッチリクエスト

public function batchAction (Request $request) 
{ 
    $requests = $request->all(); 
    $responses = []; 

    foreach ($requests as $req) { 
     $response = $this->get('some_http_client') 
      ->request($req['method'],$req['relative_url'],$req['options']); 

     $responses[] = [ 
      'method' => $req['method'], 
      'url' => $req['url'], 
      'code' => $response->getCode(), 
      'headers' => $response->getHeaders(), 
      'body' => $response->getContent() 
     ] 
    } 

    return new JsonResponse($responses) 
} 

だから、このソリューションで、私は私の機能テストは緑のだろうと思う:

は、だから私は、最も簡単な解決策のような私のアプリケーションには、コントローラ上のいくつかの要求を作ることだと思います。

ただし、サービスコンテナをX回初期化すると、アプリケーションが非常に遅くなる場合があります。各要求ごとに、すべてのバンドルが構築されるので、毎回サービスコンテナが再構築されます。

私の問題に対して他にどのような解決策がありますか?

つまり、アプリケーションの他のコントローラから応答を得るには、サーバーに完全な新しいHTTP要求を行う必要がありますか?

ありがとうございました!

+0

Controllerを使用してバッチ処理を行うのは良い方法ではないと思います。 –

+0

"Symfony Command":https://symfony.com/doc/current/console.html/"Symfony Application":http://symfony.com/doc/current/components/console/single_command_tool.htmlとGuzzleClient:http://docs.guzzlephp.org/en/latest/ –

+0

アドバイスをありがとうございます。私はコンソールソリューションを見ましたが、私のエンドポイントはコントローラで既にrouting.ymlファイルから定義されているので、私のユースケースには適切ではないと思います。ですから、コマンドを使うためには、すべてのコントローラをコマンドとして書き直し、何らかのルーティングをコマンドとリンクする必要があると思います。コマンド出力で応答する必要があります。このソリューションでは、ヘッダー、クッキーなどの厳しい要求情報にも関心があります。 – Hammerbot

答えて

3

内部的にSymfonyはhttp_kernelコンポーネントでリクエストを処理します。したがって、実行するすべてのバッチアクションのリクエストをシミュレートしてから、http_kernelコンポーネントに渡してから、その結果を精緻化することができます。

この例のコントローラー考えてみましょう:以下のコントローラメソッドで

/** 
* @Route("/batchAction", name="batchAction") 
*/ 
public function batchAction() 
{ 
    // Simulate a batch request of existing route 
    $requests = [ 
     [ 
      'method' => 'GET', 
      'relative_url' => '/b', 
      'options' => 'a=b&cd', 
     ], 
     [ 
      'method' => 'GET', 
      'relative_url' => '/c', 
      'options' => 'a=b&cd', 
     ], 
    ]; 

    $kernel = $this->get('http_kernel'); 

    $responses = []; 
    foreach($requests as $aRequest){ 

     // Construct a query params. Is only an example i don't know your input 
     $options=[]; 
     parse_str($aRequest['options'], $options); 

     // Construct a new request object for each batch request 
     $req = Request::create(
      $aRequest['relative_url'], 
      $aRequest['method'], 
      $options 
     ); 
     // process the request 
     // TODO handle exception 
     $response = $kernel->handle($req); 

     $responses[] = [ 
      'method' => $aRequest['method'], 
      'url' => $aRequest['relative_url'], 
      'code' => $response->getStatusCode(), 
      'headers' => $response->headers, 
      'body' => $response->getContent() 
     ]; 
    } 
    return new JsonResponse($responses); 
} 

を:

/** 
* @Route("/a", name="route_a_") 
*/ 
public function aAction(Request $request) 
{ 
    return new Response('A'); 
} 

/** 
* @Route("/b", name="route_b_") 
*/ 
public function bAction(Request $request) 
{ 
    return new Response('B'); 
} 

/** 
* @Route("/c", name="route_c_") 
*/ 
public function cAction(Request $request) 
{ 
    return new Response('C'); 
} 

要求の出力は次のようになります。

[ 
{"method":"GET","url":"\/b","code":200,"headers":{},"body":"B"}, 
{"method":"GET","url":"\/c","code":200,"headers":{},"body":"C"} 
] 

PS:私は私を願ってあなたが必要とするものを正しく理解している。

+0

あなたはそれを持っていると思います!私は明日それをテストする必要があります、私はあなたに情報を残して、ありがとう! – Hammerbot

+0

これはまさに私が必要としていたものと予想されていましたが、アプリケーションへのリクエストの移動をもっとよく理解してくれた 'app.php'ファイルも見ました。 – Hammerbot

+0

こんにちは@El_Matella、まさに!あなたはこのアプローチでいくつかのパフォーマンス上の利点を見つけましたか? – Matteo

0

テストスピードを最適化する方法は、PHPunitの設定(たとえば、xdebug config、または通常のPHPインスタンスにXdebugモジュールを組み込む代わりにphpdbg SAPIを使ってテストを実行する)の両方があります。

コードは常にAppKernelクラスを実行するため、テスト中にコンテナの初期化を行うなど、特定の環境でいくつかの最適化を行うこともできます。

私はone such exampleをKris Wallsmithによって使用しています。ここに彼のサンプルコードがあります。

class AppKernel extends Kernel 
{ 
// ... registerBundles() etc 
// In dev & test, you can also set the cache/log directories 
// with getCacheDir() & getLogDir() to a ramdrive (/tmpfs). 
// particularly useful when running in VirtualBox 

protected function initializeContainer() 
{ 
    static $first = true; 

    if ('test' !== $this->getEnvironment()) { 
     parent::initializeContainer(); 
     return; 
    } 

    $debug = $this->debug; 

    if (!$first) { 
     // disable debug mode on all but the first initialization 
     $this->debug = false; 
    } 

    // will not work with --process-isolation 
    $first = false; 

    try { 
     parent::initializeContainer(); 
    } catch (\Exception $e) { 
     $this->debug = $debug; 
     throw $e; 
    } 

    $this->debug = $debug; 
} 
+0

こんにちは、私の質問に答える時間を取ってくれてありがとう。あなたのテストの最適化を理解していると思います。しかし、私の質問はテスト環境を対象としていません。私が*サービスコンテナが毎回再構築されると言ったとき、私はコントローラーが '$ response = $ this-> get( 'some_http_client') - > request()'を使って各リクエストを行った後に意味しました。私の質問は、「本当に私の問題に対応するためにhttpリクエストを行う必要がありますか? – Hammerbot

関連する問題