oralunal/laravel-clickhouse
A ClickHouse database driver for Laravel that connects your app to the column-oriented analytics engine, letting you run high-speed queries through Laravel's familiar query builder and Eloquent-style APIs.
composer require oralunal/laravel-clickhouse (v4.2.0 is the current release; 4.x is the line you want on any modern Laravel).php artisan vendor:publish and pick the ClickHouse provider tag — then look at config/database.php, not the package config, because that is where you actually wire things up day to day.'clickhouse' => [
'driver' => 'clickhouse',
'host' => env('CLICKHOUSE_HOST', '127.0.0.1'),
'port' => env('CLICKHOUSE_PORT', 8123),
'database' => env('CLICKHOUSE_DATABASE', 'default'),
'username' => env('CLICKHOUSE_USERNAME', 'default'),
'password' => env('CLICKHOUSE_PASSWORD', ''),
],
php artisan make:clickhouse-migration create_events_table
php artisan make:clickhouse-model Event
Migrations drive everything (including static analysis). As of v4.2.0 the PHPStan extension reads the package's migrations to infer column types. That means the migration file is now the source of truth for both the database and your type checks — keep them in the repo, don't squash them away, and don't create tables out-of-band if you want accurate analysis.
Schema::create('events', function (Blueprint $table) {
$table->engine('MergeTree');
$table->dateTime('created_at');
$table->string('name');
$table->float('value'); // Float64 -> nullable under a read-only connection
$table->orderBy('created_at');
$table->partitionBy('toYYYYMM(created_at)');
});
Split write and read connections. Point writes at a normal connection and analytics reads at a read-only one. Since v4.2.0 the PHPStan extension marks Float32/Float64 columns nullable when the connection is read-only, which matches the fact that a read-only user can't guarantee those values — embrace it rather than fighting it, and coerce at the edges of your domain objects.
Batch inserts, never per-row saves. Use the model/query builder's bulk insert with arrays. ClickHouse punishes single-row inserts with part explosion. Chunk large payloads and let the server merge.
Materialized and ALIAS columns are read-only by definition. v4.2.0 makes them nullable in PHPStan for exactly this reason. Keep them out of $fillable/insert payloads and only read them.
Use Parallel::get() / Parallel::getRows() for fan-out dashboards. v4.2.0 fixed these to accept the query of any model, not just one specific model, so you can now pass heterogeneous model queries into a single parallel batch. This is the natural place for a dashboard hitting several aggregate tables at once.
Let PHPStan do the work. Wire the package's PHPStan/Larastan extension into phpstan.neon and run analysis in CI. The new SchemaDropCommand and SchemaIndexDefinition exist so drop()->sync() and index()->granularity() type-check cleanly — use those builder methods instead of raw statements and you keep static analysis green.
Upgrading from 3.x: run lc-upgrade-3x-to-4x. As of v4.2.0 it only recommends schema:dump for tables that no migration creates, so tables you scaffold with make:clickhouse-migration stay fully analysable.
PHPStan\ConnectionConfig::isReadOnly() is deprecated in favour of hasReadOnlyClickHouseConnection(). If you wrote custom PHPStan rules or extensions against the old method, migrate them this release — it will be removed in 5.x.NOT NULL assumption here will pass PHPStan and then fail (or silently mislead) at runtime.float $value on a DTO hydrated from a read-only connection's Float64 column, handle null explicitly.update()/delete() compile to mutations that run in the background; check system.mutations when a change "didn't take". Design tables as ReplacingMergeTree/CollapsingMergeTree and query with FINAL or argMax where you need current state.orderBy for your dominant WHERE/GROUP BY pattern before the table grows; a rebuild is a full data migration.max_insert_block_size; tiny inserts are the most common cause of "ClickHouse is slow".schema:dump lose type fidelity — that's why the upgrade command now narrows its suggestion.system.query_log over dumping query objects in the app; a stray ->dd() on a large table can pull a lot over the wire.SchemaIndexDefinition) — if you add your own ClickHouse type, register it with the schema builder and the PHPStan extension, or you'll get mixed types leaking into your models.Update your pinned version to ^4.2 and re-run both the test suite and phpstan analyse after upgrading — the type-nullability changes can surface previously hidden issues in existing code.
How can I help you explore Laravel packages today?