{"id":16486002,"url":"https://github.com/simpod/phpclickhouseclient","last_synced_at":"2025-04-10T02:29:27.549Z","repository":{"id":37889818,"uuid":"154360318","full_name":"simPod/PhpClickHouseClient","owner":"simPod","description":"PHP ClickHouse Client over HTTP","archived":false,"fork":false,"pushed_at":"2025-02-07T05:55:36.000Z","size":359,"stargazers_count":18,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-03T00:09:17.883Z","etag":null,"topics":["clickhouse","clickhouse-client","hacktoberfest","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simPod.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["simPod"]}},"created_at":"2018-10-23T16:20:10.000Z","updated_at":"2025-01-30T11:07:58.000Z","dependencies_parsed_at":"2024-05-13T10:54:16.840Z","dependency_job_id":"54f39d03-4c75-40fd-8ff1-86f03a9915bf","html_url":"https://github.com/simPod/PhpClickHouseClient","commit_stats":{"total_commits":232,"total_committers":5,"mean_commits":46.4,"dds":0.3017241379310345,"last_synced_commit":"cdb52c148f09e8fdccc07e24b54f2938f20ccfb6"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simPod%2FPhpClickHouseClient","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simPod%2FPhpClickHouseClient/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simPod%2FPhpClickHouseClient/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simPod%2FPhpClickHouseClient/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simPod","download_url":"https://codeload.github.com/simPod/PhpClickHouseClient/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248144079,"owners_count":21054865,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clickhouse","clickhouse-client","hacktoberfest","php"],"created_at":"2024-10-11T13:28:03.509Z","updated_at":"2025-04-10T02:29:27.521Z","avatar_url":"https://github.com/simPod.png","language":"PHP","funding_links":["https://github.com/sponsors/simPod"],"categories":[],"sub_categories":[],"readme":"# PHP ClickHouse Client\n\n[![Build Status](https://github.com/simPod/PhpClickHouseClient/workflows/CI/badge.svg?branch=master)](https://github.com/simPod/PhpClickHouseClient/actions)\n[![Code Coverage][Coverage image]][CodeCov Master]\n[![Downloads](https://poser.pugx.org/simpod/clickhouse-client/d/total.svg)](https://packagist.org/packages/simpod/clickhouse-client)\n[![Infection MSI](https://img.shields.io/endpoint?style=flat\u0026url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2FsimPod%2FPhpClickHouseClient%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/simPod/PhpClickHouseClient/master)\n\n## Motivation\n\nThe library is trying not to hide any ClickHouse HTTP interface specific details. \nThat said everything is as much transparent as possible and so object-oriented API is provided without inventing own abstractions.  \nNaming used here is the same as in ClickHouse docs. \n\n- Works with any HTTP Client implementation ([PSR-18 compliant](https://www.php-fig.org/psr/psr-18/))\n- All [ClickHouse Formats](https://clickhouse.yandex/docs/en/interfaces/formats/) support\n- Logging ([PSR-3 compliant](https://www.php-fig.org/psr/psr-3/))\n- SQL Factory for [parameters \"binding\"](#parameters-binding)\n- [Native query parameters](#native-query-parameters) support\n\n## Contents\n\n- [Setup](#setup)\n  - [Logging](#logging)\n  - [PSR Factories who?](#psr-factories-who)\n- [Sync API](#sync-api)\n  - [Select](#select)\n  - [Select With Params](#select-with-params)\n  - [Insert](#insert)\n- [Async API](#async-api)\n  - [Select](#select-1)\n- [Native Query Parameters](#native-query-parameters)\n- [Snippets](#snippets)\n\n## Setup\n\n```sh\ncomposer require simpod/clickhouse-client  \n```\n\n1. Read about ClickHouse [Http Interface](https://clickhouse.com/docs/en/interfaces/http/). _It's short and useful for concept understanding._\n2. Create a new instance of ClickHouse client and pass PSR factories.\n   1. Symfony HttpClient is recommended (performance, less bugs, maintenance)\n   2. The plot twist is there's no endpoint/credentials etc. config in this library, provide it via client\n3. See tests\n\n```php\n\u003c?php\n\nuse Http\\Client\\Curl\\Client;\nuse Nyholm\\Psr7\\Factory\\Psr17Factory;\nuse SimPod\\ClickHouseClient\\Client\\PsrClickHouseClient;\nuse SimPod\\ClickHouseClient\\Client\\Http\\RequestFactory;\nuse SimPod\\ClickHouseClient\\Param\\ParamValueConverterRegistry;\n\n$psr17Factory = new Psr17Factory;\n\n$clickHouseClient = new PsrClickHouseClient(\n    new Client(),\n    new RequestFactory(\n        new ParamValueConverterRegistry(),\n        $psr17Factory,\n        $psr17Factory\n    ),\n    new LoggerChain(),\n    [],\n);\n```\n\n### Symfony HttpClient Example\n\nConfigure HTTP Client\n\nAs said in ClickHouse HTTP Interface spec, we use headers to auth and e.g. set default database via query.\n\n```yaml\nframework:\n    http_client:\n        scoped_clients:\n            click_house.client:\n                base_uri: '%clickhouse.endpoint%'\n                headers:\n                    'X-ClickHouse-User': '%clickhouse.username%'\n                    'X-ClickHouse-Key': '%clickhouse.password%'\n                query:\n                    database: '%clickhouse.database%'\n```\n\n### PSR Factories who?\n\n_The library does not implement it's own HTTP. \nThat has already been done via [PSR-7, PSR-17 and PSR-18](https://www.php-fig.org/psr/). \nThis library respects it and allows you to plug your own implementation (eg. HTTPPlug or Guzzle)._\n\n_Recommended are `composer require nyholm/psr7` for PSR-17 and `composer require php-http/curl-client` for Curl PSR-18 implementation (used in example above)._\n\n## Sync API\n\n### Select\n\n`ClickHouseClient::select()`\n\nIntended for `SELECT` and `SHOW` queries. \nAppends `FORMAT` to the query and returns response in selected output format:\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Client\\ClickHouseClient;\nuse SimPod\\ClickHouseClient\\Format\\JsonEachRow;\nuse SimPod\\ClickHouseClient\\Output;\n\n/** @var ClickHouseClient $client */\n/** @var Output\\JsonEachRow $output */\n$output = $client-\u003eselect(\n    'SELECT * FROM table',\n    new JsonEachRow(),\n    ['force_primary_key' =\u003e 1]\n);\n```\n\n### Select With Params\n\n`ClickHouseClient::selectWithParams()`\n\nSame as `ClickHouseClient::select()` except it also allows [parameter binding](#parameters-binding).\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Client\\ClickHouseClient;\nuse SimPod\\ClickHouseClient\\Format\\JsonEachRow;\nuse SimPod\\ClickHouseClient\\Output;\n\n/** @var ClickHouseClient $client */\n/** @var Output\\JsonEachRow $output */\n$output = $client-\u003eselectWithParams(\n    'SELECT * FROM :table',\n    ['table' =\u003e 'table_name'],\n    new JsonEachRow(),\n    ['force_primary_key' =\u003e 1]\n);\n```\n\n### Insert\n\n`ClickHouseClient::insert()`\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Client\\ClickHouseClient;\n\n/** @var ClickHouseClient $client */\n$client-\u003einsert('table', $data, $columnNames);\n```\n\nIf `$columnNames` is provided and is key-\u003evalue array column names are generated based on it and values are passed as parameters:\n\n`$client-\u003einsert( 'table', [[1,2]], ['a' =\u003e 'Int8, 'b' =\u003e 'String'] );` generates `INSERT INTO table (a,b) VALUES ({p1:Int8},{p2:String})` and values are passed along the query.\n\nIf `$columnNames` is provided column names are generated based on it:\n\n`$client-\u003einsert( 'table', [[1,2]], ['a', 'b'] );` generates `INSERT INTO table (a,b) VALUES (1,2)`.\n\nIf `$columnNames` is omitted column names are read from `$data`:\n \n`$client-\u003einsert( 'table', [['a' =\u003e 1,'b' =\u003e 2]]);` generates `INSERT INTO table (a,b) VALUES (1,2)`.\n\nColumn names are read only from the first item:\n\n`$client-\u003einsert( 'table', [['a' =\u003e 1,'b' =\u003e 2], ['c' =\u003e 3,'d' =\u003e 4]]);` generates `INSERT INTO table (a,b) VALUES (1,2),(3,4)`.\n\nIf not provided they're not passed either:\n\n`$client-\u003einsert( 'table', [[1,2]]);` generates `INSERT INTO table VALUES (1,2)`.\n\n## Async API\n\n### Select\n\n## Parameters \"binding\"\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Sql\\SqlFactory;\nuse SimPod\\ClickHouseClient\\Sql\\ValueFormatter;\n\n$sqlFactory = new SqlFactory(new ValueFormatter());\n\n$sql = $sqlFactory-\u003ecreateWithParameters(\n    'SELECT :param',\n    ['param' =\u003e 'value']\n);\n```\nThis produces `SELECT 'value'` and it can be passed to `ClickHouseClient::select()`.\n\nSupported types are:\n- scalars\n- DateTimeInterface\n- [Expression](#expression)\n- objects implementing `__toString()`\n\n## Native Query Parameters\n\n\u003e [!TIP]\n\u003e [Official docs](https://clickhouse.com/docs/en/interfaces/http#cli-queries-with-parameters)\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Client\\PsrClickHouseClient;\n\n$client = new PsrClickHouseClient(...);\n\n$output = $client-\u003eselectWithParams(\n    'SELECT {p1:String}',\n    ['param' =\u003e 'value']\n);\n```\n\nAll types are supported (except `AggregateFunction`, `SimpleAggregateFunction` and `Nothing` by design).\nYou can also pass `DateTimeInterface` into `Date*` types or native array into `Array`, `Tuple`, `Native` and `Geo` types\n\n### Custom Query Parameter Value Conversion\n\nQuery parameters passed to `selectWithParams()` are converted into an HTTP-API-compatible format. To overwrite an existing value converter or\nprovide a converter for a type that the library does not (yet) support, pass these to the\n`SimPod\\ClickHouseClient\\Param\\ParamValueConverterRegistry` constructor:\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Client\\Http\\RequestFactory;\nuse SimPod\\ClickHouseClient\\Client\\PsrClickHouseClient;\nuse SimPod\\ClickHouseClient\\Exception\\UnsupportedParamValue;\nuse SimPod\\ClickHouseClient\\Param\\ParamValueConverterRegistry;\n\n$paramValueConverterRegistry = new ParamValueConverterRegistry([\n    'datetime' =\u003e static fn (mixed $v) =\u003e $v instanceof DateTimeInterface ? $v-\u003eformat('c') : throw UnsupportedParamValue::type($value)\n]);\n\n$client = new PsrClickHouseClient(..., new RequestFactory($paramValueConverterRegistry, ...));\n```\n\nBe aware that the library can not ensure that passed values have a certain type. They are passed as-is and closures must accept `mixed` values.\n\nThrow an exception of type `UnsupportedParamValue` if your converter does not support the passed value type.\n\n### Expression\n\nTo represent complex expressions there's `SimPod\\ClickHouseClient\\Sql\\Expression` class. When passed to `SqlFactory` its value gets evaluated.\n\nTo pass eg. `UUIDStringToNum('6d38d288-5b13-4714-b6e4-faa59ffd49d8')` to SQL:\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Sql\\Expression;\n\nExpression::new(\"UUIDStringToNum('6d38d288-5b13-4714-b6e4-faa59ffd49d8')\");\n```\n\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Sql\\ExpressionFactory;\nuse SimPod\\ClickHouseClient\\Sql\\ValueFormatter;\n\n$expressionFactory = new ExpressionFactory(new ValueFormatter());\n\n$expression = $expressionFactory-\u003etemplateAndValues(\n    'UUIDStringToNum(%s)',\n    '6d38d288-5b13-4714-b6e4-faa59ffd49d8'\n);\n```\n\n## Snippets\n\nThere are handy queries like getting database size, table list, current database etc.\n\nTo prevent Client API pollution, those are extracted into Snippets.\n\nExample to obtain current database name:\n```php\n\u003c?php\n\nuse SimPod\\ClickHouseClient\\Snippet\\CurrentDatabase;\n\n$currentDatabaseName = CurrentDatabase::run($client);\n```\n\n### List\n\n- CurrentDatabase\n- DatabaseSize\n- Parts\n- ShowCreateTable\n- ShowDatabases\n- TableSizes\n- Version\n\n[Coverage image]: https://codecov.io/gh/simPod/PhpClickHouseClient/branch/master/graph/badge.svg\n[CodeCov Master]: https://codecov.io/gh/simPod/PhpClickHouseClient/branch/master\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpod%2Fphpclickhouseclient","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimpod%2Fphpclickhouseclient","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimpod%2Fphpclickhouseclient/lists"}