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

Influxdb Client Php Laravel Package

influxdata/influxdb-client-php

Official reference PHP client library for InfluxDB 2.x (also works with InfluxDB 1.8+). Query and write data, manage buckets and tasks via the 2.x API, add default tags, write over UDP, delete data, and handle proxies and redirects.

View on GitHub
Deep Wiki
Context7

Getting Started

The client is a thin, PSR-18-based SDK — there is no Laravel service provider, facade, or config file. Plan on ~30 lines of glue code in your app before it feels native.

1. Install with an HTTP client. The library ships no transport; you must provide one. Guzzle is the pragmatic choice because the verifySSL, timeout, and proxy options only work with the default Guzzle wiring:

composer require influxdata/influxdb-client-php guzzlehttp/guzzle

2. Put credentials in config/services.php — never inline the token:

'influxdb' => [
    'url'       => env('INFLUXDB_URL', 'http://localhost:8086'),
    'token'     => env('INFLUXDB_TOKEN'),
    'bucket'    => env('INFLUXDB_BUCKET'),
    'org'       => env('INFLUXDB_ORG'),
    'precision' => \InfluxDB2\Model\WritePrecision::MS,
    'timeout'   => 10,
],

3. Bind it as a singleton in a small dedicated provider so you're not constructing clients in controllers:

$this->app->singleton(\InfluxDB2\Client::class, fn ($app) => new \InfluxDB2\Client(
    array_filter($app['config']['services.influxdb'])
));

$this->app->bind(\InfluxDB2\QueryApi::class, fn ($app) =>
    $app->make(\InfluxDB2\Client::class)->createQueryApi());

4. First use case: a write on a domain event. Most Laravel apps use this for operational metrics (request latency, queue throughput, signups per hour) — data that Flux can downsample but SQL is awkward for:

$writeApi = $client->createWriteApi();

$point = \InfluxDB2\Point::measurement('http_request')
    ->addTag('route', 'checkout.store')
    ->addTag('status', '200')
    ->addField('duration_ms', 143.2)
    ->time(now()->getTimestampMs(), \InfluxDB2\Model\WritePrecision::MS);

$writeApi->write($point);
$writeApi->close();

Where to look first: the examples/ directory in the repo, then WriteApi.php and WriteOptions.php (batching semantics are the only genuinely surprising part), then the generated API reference for QueryApi if you need streaming or parameterized queries. Skip the full management API until you actually need to provision buckets from code.

Implementation Patterns

Wrap it behind your own interface. Zero dependents and 166 stars means you are the support layer. Define interface MetricsWriter { public function record(Point $p): void; } and a thin adapter — it makes swapping the client, faking in tests, and handling the batching lifecycle vastly easier than injecting InfluxDB2\Client everywhere.

Write via Point, never hand-rolled line protocol. The builder handles quoting/escaping of tag values and measurement names. Manual strings break the first time a tag contains a comma, space, or =. Reserve raw strings for bulk imports where you control the payload entirely.

Respect the precision contract. precision in config must match the unit of the timestamp you pass to ->time(). Set MS and pass getTimestampMs()/Carbon's millisecond helpers, or NS and be careful — PHP ints are 64-bit so nanoseconds work, but mixing units silently shifts data by orders of magnitude on the time axis. Pick one precision project-wide and assert it in a test.

Choose sync vs. batch deliberately:

$writeApi = $client->createWriteApi([
    'writeType'      => \InfluxDB2\WriteType::BATCHING,
    'batchSize'      => 500,
    'flushInterval'  => 1000,   // ms
    'maxRetries'     => 3,
    'retryBufferLimit' => 5000,
]);

Synchronous (the default) is right for one-off writes in a request: it surfaces HTTP/API errors immediately as InfluxDB2\ApiException. Batching only pays off inside a long-running process — a queued job that writes thousands of points, an import command, or a queue worker loop. In a normal FPM request, batching adds buffer-loss risk with almost no throughput gain.

Flush at the right boundary. For a bulk job, wrap writes and always flush in a finally:

try {
    foreach ($rows as $row) { $writeApi->write($point); }
} finally {
    $writeApi->close();
}

If you batch inside a long-lived worker or Octane, flush on terminate or every N items — see gotchas below.

Queries: pick the return shape by size. query() returns FluxTable[] fully materialised and json_encodes cleanly for API responses; queryStream() with $parser->each() yields FluxRecord objects one at a time and is the only sane option for exports or large ranges:

$tables = $client->createQueryApi()->query(
    'from(bucket:"metrics") |> range(start: -1h) |> filter(fn: (r) => r._measurement == "http_request")'
);

return collect($tables)->flatMap(fn ($t) => $t->records)
    ->map(fn ($r) => ['time' => $r->getTime(), 'route' => $r->values['route'], 'ms' => $r->values['_value']]);

Aggregate in Flux, not PHP. |> aggregateWindow(every: 1m, fn: mean) pushes the work to the database and keeps the payload small. Fetching raw points and averaging in a Collection is the single most common way to make this integration feel slow.

Parameterize when available. On InfluxDB Cloud, Query::setParams() is the injection-safe way to vary bucket names and time bounds. On OSS it's unsupported — if you're stuck string-interpolating, validate bucket/measurement names against an allowlist rather than trusting request input.

Health check in your readiness probe. Point a /health/influx route (or a scheduled command) at the client's ping/health check so a dead Influx doesn't silently swallow all metrics. Combine with Laravel's Schedule to alert on consecutive failures.

Test with a fake PSR-18 client, not Http::fake(). Laravel's HTTP fake intercepts the HTTP facade only; this library talks to any Psr\Http\Client\ClientInterface. Inject a stub client via the httpClient option (nyholm/psr7 + a tiny ClientInterface returning canned CSV responses) and assert on the request body. Alternatively, bind your own MetricsWriter interface to a spy and keep unit tests free of the SDK entirely.

Use the management API for provisioning, not runtime. Creating buckets, tokens, and tasks from a seeder or artisan command is fine; doing it on every boot adds latency and race conditions. Cache bucket existence checks.

Gotchas and Tips

  • Batched writes are lost if you don't close(). There is no destructor you should rely on. In a queued job, put the flush in finally. In an Octane or queue:work process, the singleton client lives across requests — decide explicitly whether to flush per job (simplest) or accumulate, and cap memory with retryBufferLimit.
  • debug => true dumps to logFile, which defaults to php://output. In a Laravel web request that corrupts your JSON/HTML response. Always set logFile to storage_path('logs/influx.log'). And note debug logs include the Authorization header — never enable it in production.
  • verifySSL, timeout, and proxy are Guzzle-only. If you inject a custom httpClient (cURL, Symfony, etc.), these config keys are silently ignored and you must configure timeouts on that client instead. This is a frequent "why is it timing out at 30s" confusion.
  • The default timeout is 10 seconds. For a large Flux query that's tight. Raise timeout rather than retrying — a retried expensive query doubles server load.
  • Exceptions are InfluxDB2\ApiException carrying a status code and a partially-parsed body. Catch it around non-batched writes, log the response body (it contains the line-protocol parse error pointing at the offending field), and don't let metrics failures take down the request path — wrap writes in a try/catch that reports to your normal logger.
  • precision omitted means the server default. Your time() values then get reinterpreted. Always set it explicitly in config.
  • query() memory blows up silently. A range(start: -30d) over a high-cardinality measurement can return hundreds of thousands of records into a PHP array and OOM the worker. Add an explicit limit while developing and switch to queryStream() for anything unbounded.
  • Streaming parsers must be fully consumed or discarded. Abandoning a queryStream() loop mid-iteration leaves an open HTTP stream on the connection; iterate to the end or unset the parser before the client goes away.
  • bucket and org are required for writes but not validated at construction. A missing config value fails on first write, deep in a job. Validate the whole config array in your service provider with a clear exception at boot.
  • InfluxDB 1.7 and earlier need the older influxdb-php package. 1.8+ works via the compatibility API. Verify the server version before assuming v2 semantics (especially parameterized queries, DeleteApi, and task management, which are Cloud/2.x-only).
  • Deletes are expensive and need a time predicate. DeleteApi requires a start/stop range plus a predicate; issuing one per request will hurt server performance. Batch deletions and expect the underlying data to disappear only after the next compaction.
  • Timestamps from FluxRecord are DateTime objects in UTC. Serialize deliberately ($record->getTime()->format(DATE_ATOM)) or your charts will shift with the app timezone.
  • Extension point if you outgrow it: the httpClient constructor option is the only real seam — it lets you add tracing, retries with backoff, or a circuit breaker underneath without forking. Combined with a WriteApi decorator that owns the flush lifecycle, that covers most production needs.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core