Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api.lensmedia.nl Bundle Laravel Package

lensmedia/api.lensmedia.nl-bundle

A Symfony bundle that provides a ready-made client for the LensMedia API (api.lensmedia.nl), wiring services, configuration, and HTTP integration into your application so you can call LensMedia endpoints without building a client from scratch.

View on GitHub
Deep Wiki
Context7

Getting Started

lensmedia/api.lensmedia.nl-bundle is a Symfony bundle, not a Laravel package. That single fact drives everything below: there is no LaravelServiceProvider, no package auto-discovery, and php artisan vendor:publish will not find it. Treat it as a source of an API client you either (a) consume in a Symfony service, or (b) port into Laravel with the Http facade.

Read the release history before anything else. The latest release is explicitly a marker/archival snapshot ("Bundle right before we switched to remove API platform… just a marker so we can look back"). It adds no features and fixes nothing. Treat this version as the last known-good reference implementation, not an upgrade target. In practice: the 2023 release you may already be on and this release are functionally equivalent for your purposes — the pinning and vendoring advice below matters more than the version bump.

Read these first (in this order):

  1. composer.json — confirms the PHP/Symfony constraints, the HTTP client it pulls in (symfony/http-client / PSR-18), and whether a type: symfony-bundle autoload maps src/ to a namespace.
  2. src/DependencyInjection/Configuration.php — the config tree. This is where the real API contract lives: base URI, API key/token, timeouts, maybe a sandbox flag.
  3. src/DependencyInjection/*Extension.php — how services are wired and which aliases/IDs are public.
  4. src/Service/ (or src/Client/) — the class that actually issues requests. Everything else is plumbing around it.

Minimal Laravel use case — authenticate and pull one page of results:

// config/services.php
'lensmedia' => [
    'base_url' => env('LENSMEDIA_BASE_URL', 'https://api.lensmedia.nl'),
    'token'    => env('LENSMEDIA_TOKEN'),
    'timeout'  => 15,
],

// app/Services/LensMedia/Client.php
final class Client
{
    public function __construct(private array $config) {}

    public function get(string $path, array $query = []): array
    {
        return Http::baseUrl($this->config['base_url'])
            ->withToken($this->config['token'])
            ->timeout($this->config['timeout'])
            ->acceptJson()
            ->retry(2, 200)
            ->get($path, $query)
            ->throw()
            ->json();
    }
}

The first endpoint worth hitting is whatever the bundle's primary resource is (media/asset listing or search). Confirm the exact path from the client class rather than guessing — the config's base_url and the client's path strings must be reconciled.

Implementation Patterns

Port, don't install (Laravel). The bundle's value is its request/response mapping, not its DI wiring. Copy the client class, strip Symfony HttpClientInterface in favor of Illuminate\Support\Facades\Http, and keep the DTOs. You get the same endpoints without dragging Symfony's container into your app.

If you must run it as-is (Symfony side-car). Stand up a small Symfony app or use Symfony's HttpClient standalone via composer require symfony/http-client, then instantiate the client manually. Laravel's container can resolve a plain class via a bound closure:

$this->app->singleton(LensMediaClient::class, fn () => new LensMediaClient(
    HttpClient::create(['base_uri' => config('services.lensmedia.base_url')]),
    config('services.lensmedia.token'),
));

Wrap it in a repository, never inject the client into controllers. This is the pattern that survives the package being abandoned:

final class MediaRepository
{
    public function __construct(private Client $client) {}

    public function search(string $term, int $page = 1): Collection
    {
        return collect($this->client->get('/media', ['q' => $term, 'page' => $page])['data'])
            ->map(fn (array $row) => MediaData::fromArray($row));
    }
}

Pagination. API clients of this vintage almost always return a meta/links block. Loop with a bounded page count and a while ($page <= $maxPages) guard — never trust an unbounded next link.

Bulk work goes on the queue. Sync calls from a web request will stall on a slow upstream. Dispatch a job per page, use RateLimited middleware, and cache by request hash with Cache::remember (short TTL — 60–300s) so repeated UI hits don't hammer the API.

Testing. Http::fake() covers everything, since you've replaced the transport:

Http::fake(['api.lensmedia.nl/*' => Http::response(['data' => []], 200)]);

Assert on Http::assertSent(fn ($req) => $req->hasHeader('Authorization')) to lock in auth behavior. If you keep the Symfony client, inject a MockHttpClient instead.

Contract tests against the real API. Because stars/dependents are zero and there is no forward roadmap (the maintainers have moved off this stack — see the marker release), add one opt-in integration test (nightly CI, real token) that hits a cheap endpoint. That's your only early warning that the upstream schema moved.

Gotchas and Tips

  • No Laravel auto-discovery. composer require will succeed, then nothing happens. There's no extra.laravel block; you'll get an "unrecognized package" non-error and a class that isn't bound. Expect to wire it manually or not at all.
  • Abandonment is now confirmed, not theorized. The latest release is explicitly a marker ("just a marker so we can look back"), and it documents that the team switched away from API Platform. There is no maintenance path. Pin the exact version ("lensmedia/api.lensmedia.nl-bundle": "x.y.z" — check the real tag), commit composer.lock, and vendor the client code into app/ if the API is business-critical. Assume no upstream fixes ever.
  • Don't upgrade reflexively. The new tag adds no code value over the 2023 release. If you're already on a working version, staying put is fine — but if you do bump, re-read Configuration.php and the client class, since a "marker" release can still carry quiet changes made before the archive was cut. Diff the tag against your current version before switching.
  • Config key names drift. Symfony config trees use snake_case (base_uri, api_key); environment variables are usually mapped by the bundle but not always. Read Configuration.php and set env vars to match exactly — a silently ignored key looks identical to an auth failure.
  • Trailing-slash base_uri. Symfony's HttpClient and Guzzle differ on how base_uri + relative path concatenate. Pick one convention (baseUrl without slash, paths starting with /) and be consistent, or you'll get //media 404s.
  • Exception behavior differs. Symfony's client throws ClientExceptionInterface/ServerExceptionInterface by default on 4xx/5xx; Guzzle (which Laravel's Http uses) throws RequestException only via ->throw(). Any try/catch copied from the bundle needs the exception class swapped.
  • Auth refresh isn't handled for you. If the token is short-lived, the bundle likely takes a static key. Add a token provider / interceptor in your port rather than patching the vendor copy.
  • Response shape is untyped. Older API clients return arrays, not DTOs. Validate with a Data object (spatie/laravel-data or a plain fromArray) at the boundary so a missing field fails loudly in one place.
  • Timeouts and retries are not defaults. Set timeout and use retry() with backoff on 429/5xx only. Retrying a 401 just burns your rate limit.
  • Extension points, ranked: (1) decorate/replace the client via your own binding, (2) fork to a lensmedia/api-client VCS repo under your org — now the clear winner given the explicit archive signal, (3) subclass the client if it isn't final. Prefer (2): it makes ownership and the abandonment explicit and reviewable.
  • Debugging: log the resolved base URL, the path, and the status code at debug level; redact the Authorization header. Most integration failures on packages like this are a wrong base URL or an unset env var, not a code bug.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource