Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Запросы к другим сервисам

Курс валют, оплата, доставка, вход через соцсеть — сайт постоянно обращается к чужим API. В Symfony для этого есть компонент HttpClient: он отправляет запросы и разбирает ответы.

Запрос GET

use Symfony\Contracts\HttpClient\HttpClientInterface;
 
#[Route('/rates', name: 'rates')]
public function rates(HttpClientInterface $client): Response
{
    $response = $client->request('GET', 'https://api.example.com/rates');
 
    $data = $response->toArray();
 
    return $this->render('rates.html.twig', ['rates' => $data['rates']]);
}

toArray() превращает ответ JSON в массив.

Что можно узнать из ответа

МетодЧто возвращает
getStatusCode()Код состояния
getHeaders()Заголовки
getContent()Тело ответа строкой
toArray()Разобранный JSON

Параметры адреса

$response = $client->request('GET', 'https://api.example.com/users', [
    'query' => ['page' => 2, 'role' => 'admin'],
]);

Адрес превратится в /users?page=2&role=admin, значения будут закодированы.

Запрос POST

$response = $client->request('POST', 'https://api.example.com/orders', [
    'json' => ['product_id' => 42, 'quantity' => 2],
]);
 
$order = $response->toArray();

Ключ json кодирует данные и добавляет заголовок Content-Type. Для обычной формы используют ключ body.

Заголовки и авторизация

$response = $client->request('GET', 'https://api.example.com/me', [
    'auth_bearer' => $token,
    'headers' => ['Accept' => 'application/json'],
    'timeout' => 5,
]);

timeout ограничивает ожидание: без него медленный сервис задержит и вашу страницу.

Ошибки

Если сервис ответил кодом 4xx или 5xx, методы toArray() и getContent() бросают исключение. Сбой сети — тоже исключение:

use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
 
try {
    $data = $client->request('GET', $url)->toArray();
} catch (HttpExceptionInterface $e) {
    $code = $e->getResponse()->getStatusCode();
    // сервис ответил ошибкой
} catch (TransportExceptionInterface $e) {
    // сервис недоступен
}

Настроенный клиент

Общие параметры одного API задают в настройках:

# config/packages/framework.yaml
framework:
    http_client:
        scoped_clients:
            github.client:
                base_uri: 'https://api.github.com'
                headers:
                    Accept: 'application/vnd.github+json'
                    Authorization: 'Bearer %env(GITHUB_TOKEN)%'

Имя аргумента выбирает клиента:

public function __construct(private HttpClientInterface $githubClient) {}
 
public function repos(string $user): array
{
    return $this->githubClient->request('GET', "/users/$user/repos")->toArray();
}

Частая ошибка

Запрос отправляется не в момент вызова request(), а когда вы обращаетесь к ответу. Если не вызвать getStatusCode(), getContent() или toArray(), ошибка сервиса останется незамеченной до уничтожения объекта. Всегда читайте ответ и оборачивайте обращение к чужому сервису в try: рано или поздно он окажется недоступен.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.