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

Airtable Laravel Laravel Package

karim-tao/airtable-laravel

karim-tao/airtable-laravel integrates Airtable with Laravel, letting you work with Airtable records through Eloquent-style models. Query, create, update, and delete records using familiar Laravel syntax, with config for API tokens, bases, and tables.

View on GitHub
Deep Wiki
Context7

Getting Started

This release is the Laravel glue layer, not the Airtable SDK itself: it ships configuration, a service provider, and a PSR-18 transport that routes the underlying karim-tao/airtable-client through Laravel's Http facade. Install the package (it pulls karim-tao/airtable-client ^0.1), then:

php artisan vendor:publish --tag=airtable-config

Set credentials in .env — the merged config means publishing is optional for env-only setups, but publish it if you want to see the shape:

AIRTABLE_CLIENT_ID=
AIRTABLE_CLIENT_SECRET=
AIRTABLE_HTTP_TIMEOUT=30
AIRTABLE_HTTP_CONNECT_TIMEOUT=10

Look here first, in order:

  1. config/airtable.php — the only file with a stable, documented surface in 0.1.0.
  2. AirtableServiceProvider — confirm how the client and the PSR-18 adapter are bound, so you know what to type-hint.
  3. The upstream karim-tao/airtable-client README — table listing, record CRUD, filtering, and pagination live there. The Laravel package does not re-document them.

First use case: resolve the client from the container (do not new it up — you'd lose the injected LaravelHttpClient and your timeouts) and read one table inside a queued job or an artisan command:

use KarimTao\Airtable\Client; // check the actual FQCN in the upstream package

public function __construct(private Client $airtable) {}

public function handle(): void
{
    $records = $this->airtable->table('Contacts')->all();
}

Type-hinting works because the provider registers the binding; that's the whole point of this release.

Implementation Patterns

Wrap the client, don't sprinkle it. Put Airtable access behind one service class per base/table so the config, timeouts, and error handling stay in one place. Controllers and Livewire components should never see the SDK client.

final class AirtableContactRepository
{
    public function __construct(private Client $airtable) {}

    public function all(): Collection
    {
        return Cache::remember('airtable.contacts', now()->addMinutes(15), fn () =>
            collect($this->airtable->table('Contacts')->all())
        );
    }
}

Writes belong in jobs. Airtable rate-limits per base (5 req/s is the usual ceiling); a job with $tries, $backoff, and WithoutOverlapping gives you retry and serialisation for free. Batch creates in chunks rather than one call per record — the HTTP round trip dominates.

Lean on the Laravel HTTP layer. Because transport goes through Http, these all apply without extra wiring:

  • Http::globalMiddleware(...) for correlation-ID headers or request logging.
  • Illuminate\Http\Client\Events\RequestSending / ResponseReceived listeners for timing metrics — this is your primary debugging hook.
  • Http::fake() in tests, so you never hit Airtable in CI.

Testing pattern:

Http::preventStrayRequests();
Http::fake(['api.airtable.com/*' => Http::response(['records' => []], 200)]);

$this->get('/contacts')->assertOk();
Http::assertSentCount(1);

Multiple bases or credentials: the config supports one credential pair. If you need several, publish the config, then register named bindings in your own provider that construct additional clients with an explicitly built LaravelHttpClient. Keep the default binding untouched so the auto-discovery still works.

Environment tuning: set short connect timeouts in web requests (AIRTABLE_HTTP_CONNECT_TIMEOUT=3), long read timeouts in import commands. Since both are read from a single config file, override per-environment via .env.{env} rather than branching in code.

Gotchas and Tips

  • config:cache is a trap. Values are read from config, which is compiled. After changing any AIRTABLE_* var in a deployed environment, run php artisan config:cache again — otherwise you'll debug "expired credentials" that aren't.
  • Don't publish the config and commit it with secrets. airtable-config writes a file that sits next to your .env; keep config/airtable.php env-driven (env(...) calls intact) rather than pasting literal values.
  • Global retry middleware can duplicate writes. A naive Http::retry() applied globally will retry POSTs. Airtable has no idempotency keys — scope retries to reads, or retry at the job level with dedupe logic.
  • Http::fake() hides adapter breakage. Faking everything means a regression in LaravelHttpClient (URL construction, headers, PSR-18 request conversion) goes unnoticed. Keep one or two integration tests against a stub server or the real API in a nightly pipeline.
  • ^0.1 is pre-1.0. Any 0.1.x bump may change method signatures upstream. Pin exact versions in composer.lock, and read upstream release notes — this package's notes will not restate them.
  • Two timeout knobs, not one. AIRTABLE_HTTP_CONNECT_TIMEOUT is omitted easily; a default of 0 or a value above AIRTABLE_HTTP_TIMEOUT produces confusing transport errors rather than clean timeouts.
  • Client ID + secret implies OAuth, not a static PAT. If you were expecting to paste an AIRTABLE_API_KEY, check the upstream auth flow — tokens issued this way expire, and you'll need refresh handling the wrapper does not provide.
  • Extension points: the real seams are (a) the published config, (b) container bindings in your own service provider to swap or decorate LaravelHttpClient, and (c) global HTTP middleware. There is no facade or interface contract documented at 0.1.0, so avoid binding to concrete SDK classes in public-facing code you'd like to keep swappable.
  • Debugging checklist for a failing call: confirm the env vars are non-empty after config caching, dump the resolved config with php artisan tinker (config('airtable')), then listen to RequestSending to inspect the actual outbound request and headers. Nine times out of ten the transport is fine and a credential or base/table name is wrong.
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