Installation
composer require donkeycode/rest-bundle
Add to config/app.php under providers:
Donkeycode\RestBundle\RestServiceProvider::class,
Publish the config file:
php artisan vendor:publish --provider="Donkeycode\RestBundle\RestServiceProvider" --tag=config
Basic Usage
Define a REST client in config/rest.php:
'clients' => [
'api' => [
'base_uri' => 'https://api.example.com',
'timeout' => 30,
],
],
Inject the client into a service:
use Donkeycode\RestBundle\Client;
class MyService {
protected $client;
public function __construct(Client $client) {
$this->client = $client;
}
public function fetchData() {
return $this->client->get('api', '/endpoint');
}
}
First Use Case Fetch and decode JSON from an external API:
$response = $this->client->get('api', '/users', [
'query' => ['limit' => 10]
]);
$users = json_decode($response->getBody(), true);
Service Binding: Bind the Client interface to a specific implementation in AppServiceProvider:
$this->app->bind('Donkeycode\RestBundle\Client', function ($app) {
return new Donkeycode\RestBundle\Client($app['config']['rest.clients.api']);
});
Named Clients: Use named clients (e.g., api, stripe) for multi-service apps:
$this->client->get('stripe', '/customers');
Headers & Auth:
$this->client->post('api', '/login', [], [
'headers' => ['Authorization' => 'Bearer token123'],
]);
Middleware: Attach middleware for logging, retries, or auth:
$this->client->withMiddleware(new \Donkeycode\RestBundle\Middleware\LoggingMiddleware())
->get('api', '/data');
Streaming: Process large responses without loading into memory:
$response = $this->client->get('api', '/large-file');
$stream = $response->getBody();
while (!$stream->eof()) {
echo $stream->read(1024);
}
Error Handling:
try {
$response = $this->client->get('api', '/unreachable');
} catch (\Donkeycode\RestBundle\Exception\ClientException $e) {
Log::error('API Error: ' . $e->getMessage());
}
Queue Jobs: Offload API calls to queues:
dispatch(new FetchDataJob($client, 'api', '/data'));
Events: Trigger events on success/failure:
$this->client->get('api', '/data')->then(function ($response) {
event(new DataFetched($response));
});
base_uri in config does not end with / to avoid double slashes in requests.default. Define it explicitly:
'clients' => [
'default' => [...],
],
dd($response->getBody()->getContents()) to debug raw responses.timeout in config for slow APIs (default: 30 seconds).$this->client->withOptions(['verify' => false])->get('api', '/endpoint');
Custom Middleware: Extend Donkeycode\RestBundle\Middleware\AbstractMiddleware to add logic (e.g., rate limiting):
class RateLimitMiddleware extends AbstractMiddleware {
public function handle(RequestInterface $request, callable $next) {
// Add rate limit logic
return $next($request);
}
}
Response Transformers: Decouple API responses from your models:
$this->client->get('api', '/users')->then(function ($response) {
return User::hydrate(json_decode($response->getBody(), true));
});
Cache::remember('api_users', 3600, function () {
return $this->client->get('api', '/users');
});
Case-Sensitive Headers: Ensure headers like Content-Type match the API’s expectations.
Query Parameters: URL-encode values manually if the bundle doesn’t handle it:
$query = http_build_query(['q' => 'Laravel & REST']);
$this->client->get('api', '/search', ['query' => $query]);
Async Calls: Avoid blocking the event loop in Laravel’s request lifecycle. Use queues or sync calls judiciously.
How can I help you explore Laravel packages today?