Коли виклики до одного API розкидані по контролерах і джобах (Http::withToken(...)->get('https://...') у двадцяти місцях), будь-яка зміна - нова версія API, інший заголовок, логування - перетворюється на пошук по всьому проєкту. Налаштування треба зібрати в одному місці.
Рівень 1 - макрос з базовими налаштуваннями:
// AppServiceProvider::boot()
Http::macro('novaPoshta', fn () => Http::baseUrl(config('services.nova_poshta.url'))
->acceptJson()
->connectTimeout(3)
->timeout(10)
->retry(2, 300, fn ($e) => $e instanceof ConnectionException));
// використання
$response = Http::novaPoshta()->post('/', $payload);
Добре для невеликої кількості викликів: спільні адреса, тайм-аути, автентифікація.
Рівень 2 - клас-клієнт з методами предметної області:
final class NovaPoshtaClient
{
public function __construct(private readonly string $apiKey) {}
public function trackParcel(string $number): ParcelStatus
{
$response = Http::novaPoshta()
->post('/', [
'apiKey' => $this->apiKey,
'modelName' => 'TrackingDocument',
'calledMethod' => 'getStatusDocuments',
'methodProperties' => ['Documents' => [['DocumentNumber' => $number]]],
])
->throw();
return ParcelStatus::fromApi($response->json('data.0'));
}
}
Реєстрація в контейнері ($this->app->singleton(...) з ключем з конфігурації) і впровадження в конструктори.
Що дає клас:
- решта коду не знає про HTTP: він викликає
trackParcel()і отримує DTO, а не масив з дивними ключами провайдера; - один місце для перетворення зовнішнього формату у ваші типи - зміни провайдера не розходяться по проєкту;
- легко підмінити в тестах - фейковою реалізацією інтерфейсу або
Http::fake(); - місце для кешування, логування, обробки специфічних помилок провайдера.
Рівень 3 - SDK. Якщо провайдер має офіційний PHP SDK, часто розумно ним скористатися - але через власний клас-обгортку, щоб SDK не проник у весь код. Для власних SDK до великих API - бібліотека Saloon з конекторами, запитами, DTO й тестовими моками.
Правило: кількість шарів - за складністю інтеграції. Один виклик - макросу досить; ключова інтеграція з десятками методів (платежі, CRM, склад) - клас-клієнт або SDK з чіткими типами на вході й виході.