javer/influxdb-odm-bundle
A Symfony bundle that integrates InfluxDB with Doctrine-style object-document mapping, letting you define PHP entity classes and persist or query time-series measurements without writing raw InfluxQL by hand.
javer/influxdb-odm-bundle is thin Symfony glue around an InfluxDB ODM: it registers connection and document-manager services from YAML and lets you map PHP classes to measurements. It is not Doctrine: there are no migrations, no relational associations, and no transactional unit of work. Think “annotated DTOs plus a small persistence API.”
As of v1.4.0, the bundle requires PHP 8.1+ and adds Symfony 7 support. It also no longer requires doctrine/annotations; use PHP attributes for mapping.
Minimal path:
composer require javer/influxdb-odm-bundle:^1.4
composer show javer/influxdb-odm-bundle
php -v
// config/bundles.php
Javer\InfluxDBBundle\JaverInfluxDBBundle::class => ['all' => true],
DependencyInjection/Configuration.php; the shape is typically:# config/packages/javer_influx_db.yaml
javer_influx_db:
connections:
default:
host: '%env(INFLUXDB_HOST)%'
port: 8086
database: '%env(INFLUXDB_DATABASE)%'
username: '%env(INFLUXDB_USER)%'
password: '%env(INFLUXDB_PASSWORD)%'
# timeout, retention_policy, precision where supported
document_managers:
default:
connection: default
mappings:
App:
type: attribute
dir: '%kernel.project_dir%/src/Document'
prefix: 'App\Document'
vendor/javer/influxdb-odm), so confirm exact namespaces there. v1.4.0 no longer pulls in doctrine/annotations; use attributes.namespace App\Document;
use Javer\InfluxDB\ODM\Mapping\Annotation as ODM;
#[ODM\Measurement(name: 'api_request')]
class ApiRequest
{
#[ODM\Tag]
private string $route;
#[ODM\Tag]
private string $method;
#[ODM\Field]
private int $status;
#[ODM\Field]
private float $durationMs;
#[ODM\Timestamp]
private \DateTimeImmutable $occurredAt;
// constructor and accessors
}
use Javer\InfluxDB\ODM\DocumentManagerInterface;
final class RequestMetrics
{
public function __construct(private DocumentManagerInterface $dm) {}
public function record(ApiRequest $request): void
{
$this->dm->persist($request);
$this->dm->flush();
}
}
If autowiring fails, check the bundle service definitions and add an alias explicitly.
$repo = $this->dm->getRepository(ApiRequest::class);
$rows = $repo->findBy(['route' => '/api/orders'], ['occurredAt' => 'DESC'], 100);
Where to look first
vendor/javer/influxdb-odm-bundle/DependencyInjection/Configuration.php — source of truth for config keys.Resources/config/services.* — service ids and autowiring aliases.vendor/javer/influxdb-odm/ — mapping classes, repository API, query builder if any.First use case: record HTTP request duration and status from a kernel.terminate listener or middleware, then query the last 24 hours for a dashboard. This exercises connection config, attribute mapping, batching, timestamp handling, and querying in one pass.
Model one class per measurement. Keep measurement classes small and explicit. Tags are dimensions you filter or group by; fields are measured values; the timestamp should always be explicit. Encode units in field names (duration_ms, bytes_in) because InfluxDB stores no unit metadata.
Write in batches, flush deliberately. For high-volume writes, persist many documents and call flush() once per request or per batch rather than per point. Verify the ODM’s flush semantics first — if persist() writes immediately, the API behaves differently than Doctrine. For request-path metrics, flush after the response via kernel.terminate or a Messenger handler so InfluxDB latency never blocks users.
Make writes idempotent. InfluxDB overwrites points with the same measurement, tag set, and timestamp. For retries and backfills, set a deterministic timestamp and the same tags so replays do not duplicate data.
Use the repository for simple reads, raw InfluxQL for analytics. Repositories are convenient for “latest N by tag,” but time-series work usually means GROUP BY time(), downsampling, and aggregation. Get the connection/client service and issue InfluxQL directly; aggregate inside InfluxDB rather than pulling raw points into PHP.
Separate connections by retention policy. Use multiple document managers for different data classes — e.g. short-retention operational metrics and long-retention business KPIs. Inject the specific manager service rather than relying on the default alias.
Use attributes, not annotations. v1.4.0 removes the doctrine/annotations requirement. New and migrated code should use PHP attributes. If you still have annotation-based documents, either add doctrine/annotations explicitly or migrate them before depending on v1.4.0.
Integration points that pay off
RecordApiRequest messages, with retries and failure transport.SHOW DATABASES or a trivial query.Testing pattern. Run InfluxDB 1.x in Docker, point when@test at a separate database, and drop or use unique measurements in setUp(). Assert through direct InfluxQL, not only through the repository, so you verify what was actually written. On Symfony 7, test against v1.4.0+ so you are exercising the supported combination.
Error handling. Wrap flush() in try/catch and log failures. Metrics loss is often acceptable; silent loss is not. Because there is no rollback, a failed batch may be partially written — retries must be safe.
^1.4 when using Symfony 7.doctrine/annotations is no longer pulled in. This is good for modern attribute mapping, but it can break legacy annotation-based documents. Migrate to attributes or add doctrine/annotations yourself if you still need annotation metadata.influxdata/influxdb-client-php is the safer path.Configuration.php beats the README. Config key names often drift (document_manager vs document_managers, mapping array shape, connection options). Read the configuration tree before debugging YAML.DocumentManagerInterface cannot be injected, define an alias in services.yaml pointing at the bundle’s default manager service.bin/console cache:clear in dev and warm up in prod.flush() can leave a partial batch. Design for at-least-once delivery and idempotent points.precision setting of seconds vs milliseconds can make data look off by 1000x. Use DateTimeImmutable in UTC and be consistent per measurement.snake_case. InfluxQL requires quoting for special characters, and the ODM may not escape for you.curl -G 'http://localhost:8086/query?db=...' --data-urlencode "q=SHOW MEASUREMENTS", SHOW TAG KEYS, SHOW FIELD KEYS, and SELECT * LIMIT 5. Check HTTP status codes; write errors may be swallowed by the ODM.How can I help you explore Laravel packages today?