Пакетные запросы на Symfony

Я пытаюсь воспроизвести поведение пакета facebook просит функция на их графике api.

поэтому я думаю, что самое простое решение-сделать несколько запросов на контроллере на мое заявление типа:

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 раз может сделать приложение намного медленнее. Потому что для каждого запроса, каждый пакет построен, контейнер обслуживания перестроен каждый раз etc...

вы видите какое-либо другое решение для моей проблемы?

другими словами, Мне нужно сделать полные новые HTTP-запросы на мой сервер, чтобы получить ответы от других контроллеров в моем приложении?

заранее спасибо за Ваши советы!

2 ответов


внутренне 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: надеюсь, что я правильно понял, что вам нужно.


существуют способы оптимизации скорости тестирования, как с конфигурацией PHPunit (например, xdebug config, так и с запуском тестов с помощью PHPDBG SAPI вместо включения модуля Xdebug в обычный экземпляр PHP).

поскольку код всегда будет запускать класс AppKernel, вы также можете поместить туда некоторые оптимизации для определенных сред, включая initiali[zs]ING контейнер реже во время теста.

Я использую один такой пример Крис 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;
}