Installation:
composer require brunopicci/call-rest-api
Register the service provider in config/app.php under providers:
Brunopicci\ServicesBundle\ServicesBundle::class,
First Use Case:
Inject the RestApiService into a controller or service:
use Brunopicci\ServicesBundle\Services\RestApiService;
public function __construct(RestApiService $restApiService) {
$this->restApiService = $restApiService;
}
Make a simple GET request:
$response = $this->restApiService->call('https://api.example.com/data', 'GET');
Decode JSON response automatically:
$decodedResponse = $this->restApiService->call('https://api.example.com/data', 'GET', true);
Basic API Calls: Use the service for standard HTTP verbs (GET, POST, PUT, DELETE, etc.):
$response = $this->restApiService->call(
'https://api.example.com/users',
'POST',
false, // Decode JSON
['name' => 'John Doe'] // Request body
);
Headers and Authentication: Pass headers (e.g., for API keys or auth tokens) as an associative array:
$response = $this->restApiService->call(
'https://api.example.com/secure',
'GET',
true,
null,
['Authorization' => 'Bearer token123']
);
Error Handling: Wrap calls in try-catch blocks to handle exceptions (e.g., network errors, invalid responses):
try {
$response = $this->restApiService->call('https://api.example.com/data', 'GET');
} catch (\Exception $e) {
Log::error("API call failed: " . $e->getMessage());
return response()->json(['error' => 'Service unavailable'], 503);
}
Reusable API Clients: Create a dedicated service class for API-specific logic:
class StripeService {
public function __construct(RestApiService $restApiService) {
$this->restApiService = $restApiService;
}
public function createCustomer(array $data) {
return $this->restApiService->call(
'https://api.stripe.com/v1/customers',
'POST',
true,
$data,
['Authorization' => 'Bearer sk_test_...']
);
}
}
Configuration Management:
Store API endpoints and default headers in config/services.php:
'api' => [
'base_url' => env('API_BASE_URL', 'https://api.example.com'),
'default_headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
],
Then inject the config into the service or use dependency injection.
No Built-in Retry Logic:
The package lacks retry mechanisms for transient failures (e.g., rate limits). Implement a wrapper or use Laravel’s retry helper:
\Illuminate\Support\Facades\Retry::retry(3, function () use ($restApiService) {
return $restApiService->call('https://api.example.com/data', 'GET');
});
Limited Middleware Support: Unlike Guzzle or HTTP clients, this package doesn’t support middleware for request/response transformation. Use a decorator pattern or pre-process data manually.
No Automatic Type Handling: JSON decoding returns raw arrays. For typed responses (e.g., Eloquent models), manually map responses:
$data = $this->restApiService->call('https://api.example.com/users', 'GET', true);
return User::create($data[0]);
Underactive Development:
The package is "under heavy development," so breaking changes may occur. Pin the version in composer.json:
"brunopicci/call-rest-api": "1.0.*"
Inspect Raw Responses:
Pass false for decoding to debug raw HTTP responses:
$rawResponse = $this->restApiService->call('https://api.example.com/data', 'GET', false);
Log Headers and Payloads: Add logging before calling the service:
\Log::debug('API Request', [
'url' => 'https://api.example.com/data',
'method' => 'GET',
'headers' => ['Authorization' => 'Bearer token123'],
'body' => null,
]);
Validate API Responses: Check for HTTP status codes or custom error fields:
$response = $this->restApiService->call('https://api.example.com/data', 'GET', true);
if (isset($response['error'])) {
throw new \RuntimeException($response['error']);
}
Custom Response Handling: Extend the service to add domain-specific logic:
class CustomRestApiService extends RestApiService {
public function callWithRetry($url, $method, $decode = true, $data = null, $headers = []) {
return \Retry::retry(3, function () use ($url, $method, $decode, $data, $headers) {
return parent::call($url, $method, $decode, $data, $headers);
});
}
}
Integration with Laravel HTTP Client: Use Laravel’s built-in HTTP client for advanced features (e.g., events, middleware):
$response = Http::withHeaders(['Authorization' => 'Bearer token123'])
->get('https://api.example.com/data');
Mocking for Tests:
Mock the RestApiService in unit tests:
$mock = Mockery::mock(RestApiService::class);
$mock->shouldReceive('call')
->once()
->with('https://api.example.com/data', 'GET', true)
->andReturn(['key' => 'value']);
How can I help you explore Laravel packages today?