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 Clients Php Laravel Package

electivegroup/api-clients-php

A PHP library for working with Elective API clients, designed to be installed via Composer as a vendor package. Requires PHP 7.1 or higher and gives developers a straightforward way to integrate Elective's API services into their projects. Suitable for teams already using Composer-based workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Install pinned, not floating. The package has a single published release (2024-06-25) and no changelog, so treat every composer update as a potential breaking change:

composer require electivegroup/api-clients-php --with-all-dependencies
# then edit composer.json to the exact tag Composer resolved, e.g. "electivegroup/api-clients-php": "1.0.0"
git add composer.json composer.lock

Run the three compatibility checks before writing a line of code, because the README does not tell you what you are installing:

composer show electivegroup/api-clients-php        # version, deps, autoload namespace
composer why-not electivegroup/api-clients-php     # PHP / Guzzle conflicts vs. your stack
composer why guzzlehttp/guzzle                      # does it pin an old Guzzle that collides with Laravel?

If composer show reveals a Guzzle constraint that conflicts with Laravel's HTTP client, stop and reconsider — a hand-rolled client against Elective's REST API is usually cheaper than resolving that.

Where to look first. The README documents requirements and installation only, so the source is the documentation. Budget a half-day and read in this order:

  1. vendor/electivegroup/api-clients-php/composer.json — autoload namespace, dependency tree, whether it declares PSR-18/PSR-17.
  2. src/ top level — identify the entry-point client class, any Config/Credentials object, and the exception types. Those three shapes tell you 80% of the integration.
  3. Grep for curl, Guzzle, file_get_contents, base_uri, api_key, token — this locates the transport and the auth model.
  4. Enumerate public methods per class into a one-page capability map. This is the real deliverable of the discovery phase; without it, the only documentation of how your team talks to Elective is one engineer's memory.

First use case. Do not start in a controller. Prove the client works with a single read-only call from php artisan tinker or a throwaway artisan command, against a sandbox/non-production Elective environment:

// app/Console/Commands/ProbeElective.php — delete after the spike
$client = app(\ElectiveGroup\ApiClients\Client::class); // adjust to whatever step 2 revealed
dump($client->someReadMethod($id)); // capture the raw response shape

What you are capturing: the credential shape, whether the client is constructed manually or resolved from the container, what a success payload looks like, and what a 401/404/429 throws. Write those four things down before moving on.

Implementation Patterns

Never let the vendor namespace reach domain code. Wrap it on day one, even for the first spike-level feature — retrofitting the boundary later is the expensive version of this work.

// app/Contracts/ElectiveGateway.php
interface ElectiveGateway
{
    public function findCustomer(string $id): CustomerData;
    public function createOrder(OrderData $order): string;
}
// app/Services/Elective/ElectiveSdkGateway.php
final class ElectiveSdkGateway implements ElectiveGateway
{
    public function __construct(private \ElectiveGroup\ApiClients\Client $client) {}

    public function findCustomer(string $id): CustomerData
    {
        try {
            $raw = $this->client->customers()->get($id);
        } catch (\ElectiveGroup\ApiClients\Exception\NotFound $e) {
            throw new CustomerNotFound($id, previous: $e);
        }

        // Assert the fields you depend on rather than trusting hydration.
        return CustomerData::fromArray($raw);
    }
}

Bind in a service provider with explicit config. All connection settings live in config/elective.php, credentials come from env, and nothing calls env() outside config (otherwise config:cache breaks it):

// config/elective.php
return [
    'base_uri' => env('ELECTIVE_BASE_URI', 'https://api.elective.example/v1'),
    'api_key'  => env('ELECTIVE_API_KEY'),
    'timeout'  => (float) env('ELECTIVE_TIMEOUT', 10),
    'connect_timeout' => (float) env('ELECTIVE_CONNECT_TIMEOUT', 3),
];

Bind the client as scoped, not singleton. If the SDK caches a token or holds mutable request state on the instance, a singleton under Octane or a queue worker will leak credentials and state across requests:

$this->app->scoped(Client::class, fn ($app) => new Client(
    apiKey: config('elective.api_key'),
    baseUri: config('elective.base_uri'),
    // whichever constructor arguments step 2 revealed
));
$this->app->bind(ElectiveGateway::class, ElectiveSdkGateway::class);

Push writes to jobs, keep reads synchronous. Reads in a request are fine behind a short timeout. Writes go in a queued job with $tries = 3 and backoff() using jittered delays, because the SDK may or may not have its own retry loop — never both.

final class PushOrderToElective implements ShouldQueue
{
    public int $tries = 3;
    public array $backoff = [5, 30, 120];

    public function handle(ElectiveGateway $elective): void
    {
        $elective->createOrder($this->order); // gateway handles exception mapping
    }
}

Feature-test against the gateway, not the SDK. Mocking the vendor client means your tests break on every SDK patch, and Http::fake() only intercepts Laravel's client — if the SDK ships its own Guzzle stack or raw curl, Laravel's fakes are blind to it. Test the contract, and reserve one slow integration test per endpoint against the sandbox:

$this->mock(ElectiveGateway::class)
    ->shouldReceive('findCustomer')
    ->with('cus_123')
    ->andReturn(new CustomerData(id: 'cus_123', name: 'Acme'));

Establish the cross-cutting concerns once, in the adapter. Logging (correlation ID, latency, endpoint), error taxonomy (map vendor exceptions to your domain exceptions at the boundary), and pagination (whatever the SDK returns, normalize to a Generator or LazyCollection so call sites are uniform). Doing this per call site is how you end up with five subtly different Elective integrations.

Roll out behind a flag on a read path first. Dark-launch in staging, then one low-risk read in production, then writes. With zero dependents upstream, you are the first production user of every code path.

Gotchas and Tips

The README is a stub — plan for it. Sections are empty apart from requirements and installation. There is no endpoint inventory, no auth description, no config surface, no error contract, no versioning policy. Do not estimate an Elective-dependent feature as "add the SDK and call it"; the spike to discover the API is the work.

PHP 7.1+ is a floor, not a guarantee. The package may install fine on PHP 8.x and still hit deprecations or removed functions at runtime. Smoke-test every endpoint you actually use under your real runtime — installation success proves nothing about execution.

Treat the SDK as a foreign body in the Laravel container. It almost certainly does not implement PSR-18/PSR-17 (nothing in the metadata suggests it), which means you likely cannot inject Laravel's instrumented HTTP client underneath it. Consequences you must plan for: no automatic tracing, no shared retry policy, no proxy support, and Http::fake() won't help in tests. If transport injection turns out to be impossible, that alone can justify a thin in-house client.

Pin, commit the lockfile, and mirror or fork. Zero stars, zero dependents, one publisher, one release. If the repo disappears, your composer install in CI fails. Add a vcs repository entry pointing at your internal mirror so you control the failure mode:

"repositories": [{"type": "vcs", "url": "git@internal:mirrors/api-clients-php.git"}]

Timeouts are yours to set. Guzzle defaults are effectively "wait forever" for read and 0/infinite for connect in many configurations. If the SDK doesn't expose timeout config, you have a problem worth handling in the wrapper (or a fork) rather than discovering during an incident.

Silent schema drift is the nastiest failure mode. SDKs that hydrate DTOs from raw arrays often null unknown/missing fields instead of throwing. Elective changes customer_name to name, and your app quietly writes nulls to the database. Validate required fields in the adapter and assert on them in the contract test.

Double-retry amplification. If the SDK retries internally and your job retries, a 429 storm becomes a self-inflicted outage. Find out which layer owns retries; disable one. Add jitter either way.

Writes are non-idempotent until proven otherwise. If the SDK models idempotency keys, use them on every POST. If it doesn't, a timeout leaves you genuinely unsure whether the order was created — design a reconciliation job rather than blindly retrying.

Token refresh under concurrency. If auth is OAuth2-ish, "refresh the token" implemented naively will produce 401 spikes when several queue workers refresh simultaneously. Cache the token outside the client if you can, and alert on 401 rate, not just error rate.

No maintenance cadence means a scheduled upgrade review. With no changelog, treat every upstream release as a major: diff the source, re-run the contract tests against the sandbox, then bump. Do this on a calendar, not when something breaks.

Document as you discover. The capability map, auth flow, error taxonomy, and per-endpoint quirks belong in the repo wiki, not in the one engineer's head. The package will be the only artifact of how you talk to Elective, and it will outlive that engineer's tenure on the project.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log