Когда ваш сайт на Yii2 начинает общаться с чужими серверами — будь то отправка SMS, получение курсов валют или загрузка данных из соцсетей — возникает вопрос: как это сделать правильно? Можно, конечно, использовать встроенный cURL, но это как копать огород лопатой, когда рядом стоит трактор. Guzzle — тот самый трактор. Это мощный HTTP-клиент для PHP, который превращает работу с API в удовольствие. В этой статье я покажу, как подружить Yii2 и Guzzle, чтобы ваше приложение легко общалось с внешним миром.

Почему Guzzle, а не что-то другое

В PHP есть несколько способов отправить HTTP-запрос: cURL, file_get_contents, сторонние библиотеки. Но у каждого есть недостатки. cURL — низкоуровневый, требует много кода для обработки ошибок. file_get_contents — простой, но не умеет работать с заголовками и куками. Guzzle же предлагает удобный объектно-ориентированный интерфейс, поддержку PSR-7 (стандарт HTTP-сообщений), асинхронные запросы и кучу готовых middleware. Он как швейцарский нож для API.

В Yii2 Guzzle встраивается через компонент приложения. Это значит, что вы можете настроить его один раз в конфиге, а потом использовать в любом месте — в контроллерах, моделях, сервисах. Удобно, правда?

Правило №1: Всегда используйте компоненты Yii2 для внешних библиотек. Это упрощает тестирование и замену зависимостей.

Установка и настройка Guzzle в Yii2

Сначала установим Guzzle через Composer:

composer require guzzlehttp/guzzle

Теперь добавим его как компонент в конфигурацию приложения. Откройте файл config/web.php (или config/main.php для консоли) и добавьте секцию components:

'components' => [
    'guzzle' => [
        'class' => 'yii\httpclient\Client',
        'baseUrl' => 'https://api.example.com',
        'requestConfig' => [
            'format' => yii\httpclient\Client::FORMAT_JSON,
        ],
        'responseConfig' => [
            'format' => yii\httpclient\Client::FORMAT_JSON,
        ],
    ],
],

Подождите, это не Guzzle! Это встроенный HTTP-клиент Yii2, который тоже использует Guzzle под капотом. Если хотите работать напрямую с Guzzle, настройте так:

'components' => [
    'guzzle' => [
        'class' => 'GuzzleHttp\Client',
        'base_uri' => 'https://api.example.com',
        'timeout'  => 10.0,
    ],
],

Теперь в любом месте приложения можно вызвать Yii::$app->guzzle и отправлять запросы.

Пример: получение данных с внешнего API

Допустим, нам нужно получить список пользователей с сервиса JSONPlaceholder. Создадим простой контроллер:

namespace app\controllers;

use Yii;
use yii\web\Controller;

class UserController extends Controller
{
    public function actionIndex()
    {
        $client = Yii::$app->guzzle;
        $response = $client->get('https://jsonplaceholder.typicode.com/users');
        
        if ($response->getStatusCode() == 200) {
            $users = json_decode($response->getBody(), true);
            return $this->render('index', ['users' => $users]);
        } else {
            Yii::error('Ошибка при получении пользователей: ' . $response->getReasonPhrase());
            throw new \yii\web\HttpException(502, 'Внешний сервис недоступен');
        }
    }
}

Обратите внимание на проверку статуса. Всегда проверяйте HTTP-код ответа. Если сервер вернул 500, а вы не проверили, приложение может упасть.

Отправка POST-запроса с данными

Теперь представьте, что нужно зарегистрировать пользователя на внешнем сервисе. Отправим POST-запрос с JSON:

$client = Yii::$app->guzzle;
$response = $client->post('https://api.example.com/users', [
    'json' => [
        'name' => 'Иван Иванов',
        'email' => 'ivan@example.com',
    ],
    'headers' => [
        'Authorization' => 'Bearer ' . $accessToken,
    ],
]);

$statusCode = $response->getStatusCode();
$body = $response->getBody()->getContents();

Ключ json автоматически сериализует массив в JSON и установит заголовок Content-Type. А headers позволяет добавить токен авторизации. Удобно, не правда ли?

Обработка ошибок и повторные попытки

Внешние сервисы не всегда стабильны. Сервер может вернуть 503 (Service Unavailable) или соединение оборвётся. Guzzle позволяет настроить повторные попытки через middleware. Для этого установите библиотеку guzzlehttp/retry-subscriber или используйте встроенный механизм:

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;

$handlerStack = HandlerStack::create();
$handlerStack->push(Middleware::retry(function ($retries, $request, $response, $exception) {
    // Повторяем до 3 раз, если ошибка сервера
    return $retries < 3 && $response && $response->getStatusCode() >= 500;
}, function ($retries) {
    // Задержка между попытками: 1 секунда, потом 2, потом 4
    return 1000 * pow(2, $retries);
}));

$client = new Client(['handler' => $handlerStack]);

Этот код автоматически повторяет запрос, если сервер вернул ошибку 5xx, с экспоненциальной задержкой. Не забудьте также обработать исключения GuzzleHttp\Exception\ConnectException — они возникают при проблемах с сетью.

Лайфхак: Всегда оборачивайте вызовы Guzzle в try-catch. Исключения — это нормально, их нужно ловить и логировать.

Сравнение: Guzzle vs встроенный HTTP-клиент Yii2

Характеристика Guzzle напрямую Yii2 HTTP Client
Гибкость Высокая (middleware, пулы) Средняя (ограниченный набор)
Асинхронность Есть Нет
Простота настройки Требует ручной конфигурации Из коробки работает с Yii2
Поддержка PSR-7 Да Да (через Guzzle)
Рекомендуется для Сложных интеграций Простых запросов

Если вам нужно быстро сделать пару запросов — используйте встроенный клиент Yii2. Если планируется сложная логика с повторными попытками, потоками или асинхронностью — берите Guzzle напрямую.

Итоговое резюме

Интеграция Yii2 с внешними сервисами через Guzzle — это просто и эффективно. Вы получаете мощный инструмент для работы с HTTP, который легко настраивается через компонент приложения. Не забывайте проверять статусы ответов, обрабатывать исключения и использовать повторные попытки для критичных запросов. В результате ваше приложение станет надёжнее и быстрее.

Главное — не усложняйте. Начните с простого GET-запроса, а потом добавляйте middleware и обработку ошибок. И помните: Guzzle — ваш друг, а не враг.

Студия WNDER