Installation
composer require yyy/fetchapi
Publish Configuration
php artisan vendor:publish --provider="YYY\FetchApi\Pay\ServiceProvider"
config/fetchapi.php and update API endpoints, credentials, or default settings.First Use Case: Making an API Request
use YYY\FetchApi\Pay\Api;
$api = new Api(config('fetchapi.default_endpoint'));
$response = $api->get('/endpoint', ['param' => 'value']);
Stubbing for Testing
use YYY\FetchApi\Pay\Stub;
$stub = new Stub();
$response = $stub->mockResponse('/endpoint', ['status' => 200, 'data' => []]);
Request Handling
Api class for HTTP requests with built-in methods (get, post, put, delete).RequestData class for structured payloads:
$requestData = new RequestData(['key' => 'value']);
$response = $api->post('/endpoint', $requestData);
Interface-Driven Development
InterfacePay, InterfaceApi) for type safety and dependency injection:
class MyPayService implements InterfacePay {
public function processPayment(RequestData $data) {
$api = new Api(config('fetchapi.endpoints.payment'));
return $api->post('/pay', $data);
}
}
Event Handling
InterfaceEvent to listen to API lifecycle events (e.g., onBeforeRequest, onAfterResponse):
class MyEventListener implements InterfaceEvent {
public function onBeforeRequest($request) {
// Modify request (e.g., add auth headers)
}
}
Stubbing for Tests
Api with Stub in tests to mock responses:
$this->app->bind(Api::class, function () {
return new Stub();
});
Api calls in middleware for logging, retries, or auth.AppServiceProvider:
$this->app->bind(InterfaceApi::class, function () {
return new Api(config('fetchapi.endpoints.default'));
});
config('fetchapi') for dynamic endpoint switching.Configuration Overrides
config/fetchapi.php is included in config/app.php under files.Api constructor may conflict with published config. Explicitly pass endpoints:
$api = new Api(config('fetchapi.endpoints.custom'));
Stubbing Quirks
Stub does not auto-register. Manually bind it in tests or use a trait:
trait UsesFetchApiStub {
protected function stubApi() {
$this->app->bind(Api::class, Stub::class);
}
}
Interface Inconsistencies
InterfaceErr is undocumented. Assume it handles errors; implement custom error parsing if needed:
try {
$response = $api->get('/endpoint');
} catch (Exception $e) {
$errorHandler = new MyErrorHandler();
$errorHandler->handle($e);
}
RequestData Validation
RequestData lacks built-in validation. Use Laravel’s Validator or a library like respect/validation:
use Respect\Validation\Validator as v;
if (!v::keySet(['required_field'])->validate($requestData->toArray())) {
throw new \InvalidArgumentException('Missing required field');
}
Logging Responses
Add a listener to InterfaceEvent:
public function onAfterResponse($response) {
\Log::debug('API Response:', ['data' => $response->getData()]);
}
Retry Logic Implement exponential backoff in middleware:
$api->withRetry(3, function ($attempt) {
return $attempt <= 3;
});
Endpoint Switching Use config caching to avoid runtime lookups:
$endpoint = config('fetchapi.endpoints.' . config('app.env'));
Custom Request Methods
Extend Api to add methods like patch or head:
class ExtendedApi extends Api {
public function patch($endpoint, $data = []) {
return $this->request('PATCH', $endpoint, $data);
}
}
Response Decorators
Create a decorator for Api to transform responses:
class ResponseDecorator {
public function __construct(private Api $api) {}
public function get($endpoint) {
$response = $this->api->get($endpoint);
return $this->transform($response);
}
private function transform($response) {
// Custom logic (e.g., flatten arrays)
return $response->getData();
}
}
Event-Driven Extensions
Dispatch Laravel events in InterfaceEvent implementations:
public function onAfterResponse($response) {
event(new ApiResponseEvent($response));
}
How can I help you explore Laravel packages today?