imiskuf/basic-api-bundle
imiskuf/basic-api-bundle is a lightweight PHP package for quickly scaffolding basic API endpoints. It provides a simple structure and reusable components to help expose JSON data with minimal configuration and boilerplate, making it suitable for small services and prototypes.
Reality check before you type composer require: this is a Symfony bundle, not a Laravel package. It has type: symfony-bundle semantics, DI extension classes under DependencyInjection/, and Resources/config/services.yaml. There is no Illuminate\Support\ServiceProvider, no extra.laravel block, and no config/*.php to publish. If you're in a Laravel codebase, "installing" it is the wrong framing — you're reading source to port it, not adopting a dependency.
Minimal path, in order:
composer.json on GitHub first. Check autoload.psr-4 for the root namespace, the require block for the Symfony/PHP floor (a bundle from the Symfony 3.4/4.x era will pin symfony/* versions that clash with anything modern), and whether it's type: symfony-bundle. If the constraint is ^3.4 || ^4.0, stop — it will not resolve against a current Laravel app.composer require imiskuf/basic-api-bundle in a throwaway Laravel project, not your real one. Expected outcome: a resolution conflict. That failure is the fastest confirmation that you should vendor rather than install.src/ — specifically any DependencyInjection/Configuration.php (the config tree: base URI, auth, timeouts) and whatever sits in src/Service/ or src/Client/. That client class is the entire package's value. The rest is Symfony plumbing you'll discard.config/bundles.php in Laravel and no reason to fake one.First use case to port: a base-URI + credentials HTTP client you inject into a single service class, called from a controller or a queued job — one third-party API, low-consequence surface. That's the whole pattern the package encodes.
If you are genuinely on Symfony (rare given your stack): register in config/bundles.php, configure under config/packages/basic_api.yaml using the keys exposed by Configuration.php, inject credentials via %env(API_BASE_URI)% / %env(API_TOKEN)%, and constructor-inject the client into an adapter service — never call it straight from a controller.
If you are on Laravel — the realistic path — port, don't install:
app/Services/VendorName/ApiClient.php. Delete the DependencyInjection, Resources/config, and any Extension classes; they are Symfony-only.Illuminate\Support\Facades\Http. You keep the package's shape (method-per-endpoint, DTOs, endpoint constants) and drop the transport, which is the part Laravel already gives you.ServiceProvider:
$this->app->singleton(ApiClient::class, fn () =>
new ApiClient(
baseUri: config('services.vendor.base_uri'),
token: config('services.vendor.token'),
)
);
services.php entry ('vendor' => ['base_uri' => env('VENDOR_API_URI'), 'token' => env('VENDOR_API_TOKEN')]). Never let the ported class read $_ENV or getenv() directly — that's the habit Symfony bundles fall into and it bypasses Laravel's config cache.VendorApiContract) and bind the interface, not the concrete class. Because the source is unmaintained, the whole point is that a swap costs one binding.app/Services/VendorName/OrdersGateway.php) that maps the raw payload into your own DTOs. Do not let the package's response array shape leak into controllers or models.Http::retry(3, 200, throw: false), explicit ->timeout(5) / ->connectTimeout(2), and a 429 handler. The bundle almost certainly ships none of this; you're adding it on port, not inheriting it.Contract tests over unit tests. Point the ported client at a mocked Http::fake() for happy paths, and at a real upstream (staging or recorded fixtures) for the DTO mapping. The upstream contract is what drifts; the bundle itself has no test suite to lean on.
composer.json. If it resolves, audit its require tree with composer audit immediately — its HTTP and serialization transitives are unaudited.php artisan vendor:publish. There is nothing to publish. The config is a Symfony Configuration tree, which you reimplement as config/services.php.getenv(). If you copy a class that reads environment variables directly, php artisan config:cache will freeze the value (or blank it) and you'll chase a "works in dev, broken in prod" bug. Always route through config().Http::fake() for shape, and Http::dd() when you need to inspect an actual outbound request. Log the request ID and latency from within the adapter, not the client — the client should stay dumb.Http client (or Saloon) and skip the bundle entirely. That's a legitimate, common outcome.app/Services/… or a private VCS repo — never a Packagist dependency you can't patch. MIT makes this trivially legal.Http directly. Saving a day of typing isn't worth owning an unfamiliar Symfony bundle forever.How can I help you explore Laravel packages today?