PHP client for ClickHouse — fast, lightweight, no dependencies beyond ext-curl.
- Sync & async (parallel) SELECT queries
- Native query parameters — server-side
{name:Type}binding, SQL injection impossible - Rich type system — Int64, Decimal, UUID, IPv4/IPv6, DateTime64, Date32, Map, Tuple
- Bulk inserts: arrays, CSV files, streams
- Generators — memory-efficient iteration for large resultsets
- HTTP compression (gzip) for inserts
- Parameter bindings & SQL templates
- Per-query settings — override ClickHouse settings per request
- Cluster support — auto-discovery, health checks, replicas
- Streaming read/write with closures
- Progress callbacks for SELECT and INSERT
- Structured exceptions — ClickHouse error name, query ID
- Sessions, write-to-file, INSERT statistics
- HTTPS, SSL CA, IPv6 support
- Multiple auth methods (none, header, basic auth, query string)
- PHP 8.0+
- ext-curl
- ext-json
Version compatibility:
| PHP | phpClickHouse |
|---|---|
| 5.6 | <= 1.1.2 |
| 7.2 | <= 1.3.10 |
| 7.3 | 1.4.x – 1.5.x |
| 8.0+ | >= 1.6.0 |
composer require smi2/phpclickhouse$db = new ClickHouseDB\Client([
'host' => '127.0.0.1',
'port' => '8123',
'username' => 'default',
'password' => '',
]);
$db->database('default');
$db->setTimeout(10);
$db->setConnectTimeOut(5);
$db->ping(true); // throws exception on failure$statement = $db->select('SELECT * FROM my_table WHERE id = :id', ['id' => 42]);
$statement->rows(); // all rows
$statement->fetchOne(); // first row
$statement->count(); // row count// Server-side typed binding — SQL injection impossible at protocol level
$result = $db->selectWithParams(
'SELECT * FROM users WHERE id = {id:UInt32} AND name = {name:String}',
['id' => 42, 'name' => 'Alice']
);$db->insert('my_table',
[
[time(), 'key1', 100],
[time(), 'key2', 200],
],
['event_time', 'key', 'value']
);// Memory-efficient — one row at a time, no OOM
foreach ($db->selectGenerator('SELECT * FROM huge_table') as $row) {
processRow($row);
}$db->write('CREATE TABLE IF NOT EXISTS my_table (id UInt32, name String) ENGINE = MergeTree ORDER BY id');
$db->write('DROP TABLE IF EXISTS my_table');Detailed guides with examples are available in the doc/ directory:
- Quick Start & Basics — connection, select, insert, write, Statement API
- Async Queries — parallel selects, batch file inserts, error handling
- Bindings & Conditions — parameter binding, SQL templates, conditions
- Settings & Configuration — timeouts, compression, HTTPS, auth methods, sessions
- Native Query Parameters — server-side
{name:Type}binding - ClickHouse Types — Int64, Decimal, UUID, IPv4/IPv6, DateTime64, Date32, Map, Tuple
- Generators — memory-efficient
selectGenerator()for large resultsets - Per-Query Settings — override settings per request
- Streaming — streamRead, streamWrite, closures, gzip
- Cluster — multi-node setup, replicas, truncate, master node
- Structured Exceptions — error codes, exception names, query ID
- Progress Function — real-time progress for SELECT and INSERT
- INSERT Statistics — written_rows, written_bytes via X-ClickHouse-Summary
- Advanced Features — partitions, table sizes, write-to-file, logging, debug
# Start both ClickHouse versions (21.9 + 26.3)
docker-compose -f tests/docker-compose.yaml up -d
# Run tests against ClickHouse 21.9
./vendor/bin/phpunit -c phpunit-ch21.xml
# Run tests against ClickHouse 26.3
./vendor/bin/phpunit -c phpunit-ch26.xml
# Static analysis (PHPStan level 5)
./vendor/bin/phpstan analyse --memory-limit=512M
# Code style
./vendor/bin/phpcsSee CLAUDE.md for project architecture and contribution guidelines.
MIT — see LICENSE
See CHANGELOG.md