Installation:
composer require brzuchal/rest-client
Register the service provider in config/app.php (if using Laravel):
'providers' => [
// ...
Brzuchal\RestClient\RestClientServiceProvider::class,
],
Publish config (optional):
php artisan vendor:publish --provider="Brzuchal\RestClient\RestClientServiceProvider"
First Request (Laravel): Use the facade for quick access:
use Brzuchal\RestClient\Facades\RestClient;
$response = RestClient::get('https://api.example.com/users');
$data = $response->json();
First Use Case: Fetch and deserialize a JSON API response into a Laravel Eloquent model:
$user = RestClient::get('https://api.example.com/users/1')
->toEntity(User::class); // Assumes `User` implements `JsonSerializable`
Fluent Request Building: Chain methods for clarity and reusability:
$client = RestClient::create('https://api.example.com')
->withHeaders(['Authorization' => 'Bearer token'])
->withTimeout(30);
$response = $client->get('/users')->withQuery(['active' => true]);
Response Handling:
$response->getContent()$response->json()$response->toEntity(User::class)$response->validate(function ($data) { ... })Laravel Integration:
$this->app->bind('api.client', function () {
return RestClient::create(config('services.api.base_url'))
->withAuth(config('services.api.token'));
});
public function __construct(private RestClient $client) {}
Error Handling:
RestClient::onError():
RestClient::onError(function ($exception) {
Log::error('API Error', ['exception' => $exception]);
throw new \RuntimeException('API Unavailable');
});
try {
$response = $client->get('/users')->throw();
} catch (\Brzuchal\RestClient\Exception\ApiException $e) {
// Handle 4xx/5xx responses
}
Testing:
RestClient::mock():
RestClient::mock('https://api.example.com/users', [
'id' => 1,
'name' => 'Test User'
]);
Synchronous by Design:
dispatch(new FetchUsersFromApi($client));
Entity Deserialization:
JsonSerializable or use __construct(array $data):
class User implements JsonSerializable {
public function __construct(private array $data) {}
public function jsonSerialize(): array { return $this->data; }
}
Symfony HttpClient Under the Hood:
Symfony\Contracts\HttpClient\HttpClientInterface. Use the exchange method for custom handling:
$response = $client->get('/users')->exchange(function ($response) {
return $response->getContent(); // Custom logic
});
Config Overrides:
vendor:publish) may conflict with Laravel’s config/services.php. Merge explicitly:
config(['rest-client' => array_merge(
config('rest-client'),
['timeout' => 60]
)]);
Rate Limiting:
$client->withMiddleware(new RateLimitMiddleware());
Enable Verbose Logging:
$client->withOptions(['debug' => true]);
Logs will include request/response bodies.
Inspect Headers:
$headers = $client->get('/users')->getHeaders();
Test Locally:
Use RestClient::mock() to avoid hitting external APIs during development.
Custom Entity Mappers:
Extend Brzuchal\RestClient\Mapper\EntityMapper for complex deserialization:
class CustomMapper extends EntityMapper {
protected function map(array $data, string $class): object {
return new $class($data['custom_key']);
}
}
Service Factory: For dynamic API clients (experimental):
$factory = new \Brzuchal\RestClient\ServiceFactory();
$client = $factory->create('stripe', [
'base_uri' => 'https://api.stripe.com',
'auth' => 'sk_test_...'
]);
Event Listeners:
Attach to rest-client.request and rest-client.response events (if using Laravel Events):
event(new RestClientRequestEvent($request));
Middleware Stack: Add custom middleware (Symfony-style):
$client->withMiddleware(new class implements HttpClientInterface {
public function __invoke(RequestStack $stack, $uri, array $options = []) {
// Pre-process request
$response = $stack->next($uri, $options);
// Post-process response
return $response;
}
});
How can I help you explore Laravel packages today?