# PhpClickHouseClient **Repository Path**: mirrors_simPod/PhpClickHouseClient ## Basic Information - **Project Name**: PhpClickHouseClient - **Description**: PHP ClickHouse Client over HTTP - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-19 - **Last Updated**: 2026-10-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PHP ClickHouse Client [![Build Status](https://github.com/simPod/PhpClickHouseClient/workflows/CI/badge.svg?branch=master)](https://github.com/simPod/PhpClickHouseClient/actions) [![Code Coverage][Coverage image]][CodeCov Master] [![Downloads](https://poser.pugx.org/simpod/clickhouse-client/d/total.svg)](https://packagist.org/packages/simpod/clickhouse-client) [![Infection MSI](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2FsimPod%2FPhpClickHouseClient%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/simPod/PhpClickHouseClient/master) ## Motivation The library is trying not to hide any ClickHouse HTTP interface specific details. That said everything is as much transparent as possible and so object-oriented API is provided without inventing own abstractions. Naming used here is the same as in ClickHouse docs. - Works with any HTTP Client implementation ([PSR-18 compliant](https://www.php-fig.org/psr/psr-18/)) - All [ClickHouse Formats](https://clickhouse.com/docs/en/interfaces/formats/) support - Logging ([PSR-3 compliant](https://www.php-fig.org/psr/psr-3/)) - SQL Factory for [parameters "binding"](#parameters-binding) - [Native query parameters](#native-query-parameters) support ## Contents - [Setup](#setup) - [Logging](#logging) - [PSR Factories who?](#psr-factories-who) - [Sync API](#sync-api) - [Select](#select) - [Select With Params](#select-with-params) - [Insert](#insert) - [Async API](#async-api) - [Select](#select-1) - [Parameters "binding"](#parameters-binding) - [Native Query Parameters](#native-query-parameters) - [Custom Query Parameter Value Conversion](#custom-query-parameter-value-conversion) - [Expression](#expression) - [Snippets](#snippets) ## Setup ```sh composer require simpod/clickhouse-client ``` 1. Read about ClickHouse [HTTP Interface](https://clickhouse.com/docs/en/interfaces/http/). _It's short and useful for concept understanding._ 2. Create a new instance of ClickHouse client and pass a PSR-18 HTTP client plus PSR-17 factories. 1. Symfony HttpClient is recommended for the PSR-18 client. 2. The plot twist is there's no endpoint/credentials etc. config in this library, provide it via client. 3. See tests ```php 'http://localhost:8123', 'headers' => [ 'X-ClickHouse-User' => 'default', 'X-ClickHouse-Key' => '', ], 'query' => ['database' => 'default'], ]), ), new RequestFactory( new ParamValueConverterRegistry(), $psr17Factory, $psr17Factory, $psr17Factory ), ); ``` ### Logging Pass a `SqlLogger` implementation as the third `PsrClickHouseClient` constructor argument. The library provides a PSR-3 adapter: ```php select( 'SELECT * FROM table', new JsonEachRow(), new ArraySettingsProvider(['force_primary_key' => 1]) ); ``` ### Select With Params `ClickHouseClient::selectWithParams()` Same as `ClickHouseClient::select()` except it also allows [parameter binding](#parameters-binding). ```php selectWithParams( 'SELECT * FROM table WHERE name = :name', ['name' => 'Alice'], new JsonEachRow(), new ArraySettingsProvider(['force_primary_key' => 1]) ); ``` ### Insert `ClickHouseClient::insert()` ```php insert('table', $data, $columnNames); ``` If `$columnNames` is provided and is key->value array column names are generated based on it and values are passed as parameters: `$client->insert( 'table', [[1,2]], ['a' => 'Int8', 'b' => 'String'] );` generates `INSERT INTO table (a,b) VALUES ({p1:Int8},{p2:String})` and values are passed along the query. If `$columnNames` is provided column names are generated based on it: `$client->insert( 'table', [[1,2]], ['a', 'b'] );` generates `INSERT INTO table (a,b) VALUES (1,2)`. If `$columnNames` is omitted column names are read from `$data`: `$client->insert( 'table', [['a' => 1,'b' => 2]]);` generates `INSERT INTO table (a,b) VALUES (1,2)`. Column names are read only from the first item: `$client->insert( 'table', [['a' => 1,'b' => 2], ['c' => 3,'d' => 4]]);` generates `INSERT INTO table (a,b) VALUES (1,2),(3,4)`. If not provided they're not passed either: `$client->insert( 'table', [[1,2]]);` generates `INSERT INTO table VALUES (1,2)`. ## Async API ### Select `ClickHouseAsyncClient::select()` returns an Amp `Future`: ```php 'default', 'X-ClickHouse-Key' => '', ], ); $output = $client->select('SELECT 1 AS data', new JsonEachRow())->await(); ``` ## Parameters "binding" ```php createWithParameters( 'SELECT :param', ['param' => 'value'] ); ``` This produces `SELECT 'value'` and it can be passed to `ClickHouseClient::select()`. Supported types are: - scalars - null - arrays, including `IN (:list)` values and tuple arrays - backed enums - DateTimeInterface - [Expression](#expression) - objects implementing `__toString()` ## Native Query Parameters > [!TIP] > [Official docs](https://clickhouse.com/docs/en/interfaces/http#cli-queries-with-parameters) ```php selectWithParams( 'SELECT {p1:String}', ['p1' => 'value'], new JsonEachRow(), ); ``` All types are supported (except `AggregateFunction`, `SimpleAggregateFunction` and `Nothing` by design). You can also pass `DateTimeInterface` into `Date*` types or native array into `Array`, `Tuple`, `Nested` and Geo types (`Point`, `Polygon`, `Geometry` etc.). Pass raw strings to native `String` and `FixedString` parameters. The client escapes backslashes and control characters for ClickHouse; do not escape these values yourself. This also applies to `Nullable` and `LowCardinality` string wrappers. ### Custom Query Parameter Value Conversion Query parameters passed to `selectWithParams()` are converted into an HTTP-API-compatible format. To overwrite an existing value converter or provide a converter for a type that the library does not (yet) support, pass these to the `SimPod\ClickHouseClient\Param\ParamValueConverterRegistry` constructor: ```php static fn (mixed $v, mixed ...$unused) => $v instanceof DateTimeInterface ? $v->format('c') : throw UnsupportedParamValue::type($v), ]); $client = new PsrClickHouseClient(..., new RequestFactory($paramValueConverterRegistry, ...)); ``` Be aware that the library cannot ensure that passed values have a certain type. They are passed as-is and closures must accept `mixed` values. Throw an exception of type `UnsupportedParamValue` if your converter does not support the passed value type. ### Expression To represent complex expressions there's `SimPod\ClickHouseClient\Sql\Expression` class. When passed to `SqlFactory` its value gets evaluated. To pass eg. `UUIDStringToNum('6d38d288-5b13-4714-b6e4-faa59ffd49d8')` to SQL: ```php templateAndValues( 'UUIDStringToNum(%s)', '6d38d288-5b13-4714-b6e4-faa59ffd49d8' ); ``` ## Snippets There are handy queries like getting database size, table list, current database etc. To prevent Client API pollution, those are extracted into Snippets. Example to obtain current database name: ```php