1. Go to this page and download the library: Download ysfkc/clickhouse library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
// Allowed: = != <> > < >= <= LIKE NOT LIKE ILIKE NOT ILIKE IN NOT IN
$response = QueryBuilder::table('events')
->where('user_id', '>', 100, 'Int32')
->where('browser', 'LIKE', '%Chrome%', 'String')
->where('country_code', '!=', 'XX', 'String')
->get();
$response = QueryBuilder::raw(
'SELECT
toDate(event_date) AS day,
COUNT() AS total,
uniqExact(uuid) AS unique_users
FROM events
WHERE user_id = {userId:Int32}
AND event_date BETWEEN {start:Date} AND {end:Date}
GROUP BY day
ORDER BY day ASC',
['userId' => 123, 'start' => '2026-01-01', 'end' => '2026-03-31']
)->get();
$debug = QueryBuilder::table('events')
->select(['user_id', 'COUNT() as cnt'])
->where('user_id', '=', 123, 'Int32')
->groupBy(['user_id'])
->toSql();
// [
// 'query' => 'SELECT user_id, COUNT() as cnt FROM events WHERE user_id = {user_id_0:Int32} GROUP BY user_id',
// 'params' => ['user_id_0' => 123],
// ]
// ✅ Correct
$response = MetricSnapshot::rawQuery(
'SELECT toDate(recorded_at) AS day, source, AVG(value) AS avg_value
FROM metric_snapshots
WHERE status = {status:String}
AND event_date BETWEEN {start:Date} AND {end:Date}
GROUP BY day, source ORDER BY avg_value DESC LIMIT {lim:Int32}',
['status' => 'ok', 'start' => '2026-01-01', 'end' => '2026-03-31', 'lim' => 50]
);
// ❌ Incorrect
$response = MetricSnapshot::rawQuery('SELECT * FROM metric_snapshots WHERE source = ' . $userInput);
use Ysfkc\ClickHouse\ClickHouseClientService;
$client = ClickHouseClientService::getInstance();
$response = $client->select(
'SELECT source, AVG(value) as avg FROM metric_snapshots WHERE status = {s:String} GROUP BY source',
['s' => 'ok']
);
$response = $client->insert(
'INSERT INTO metric_snapshots (uuid, source, metric_name, value, event_date) VALUES ({u:String},{s:String},{m:String},{v:Float64},{d:Date})',
['u' => 'some-uuid', 's' => 'api', 'm' => 'response_time', 'v' => 142.5, 'd' => '2026-04-06']
);
// SSRF/LFI/exfiltration vectors are automatically blocked
$response = $client->command('OPTIMIZE TABLE metric_snapshots FINAL');
// ✅ Preferred
->where('user_id', '=', $userId, 'Int32')
// ⚠️ Last resort — column expressions only, no user input
->whereRaw('toYear(event_date) = toYear(today())')
use Ysfkc\ClickHouse\Logger\PhalconLoggerAdapter;
use Ysfkc\ClickHouse\ClickHouseClientService;
use Ysfkc\ClickHouse\Model\ClickHouseBaseModel;
$adapter = new PhalconLoggerAdapter($di->get('logger'));
ClickHouseClientService::configure(
$di->getConfig()->clickhouse->toArray(),
$adapter
);
ClickHouseBaseModel::setDefaultLogger($adapter);
POST http://clickhouse:8123/?database=analytics¶m_userId=123&default_format=JSON
Body: SELECT * FROM events WHERE user_id = {userId:Int32}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.