smi2/phpclickhouse
PHP client for ClickHouse with an easy, fluent API. Supports queries and inserts, result sets, bindings, and connection configuration for fast analytics workflows. Suitable for Laravel and standalone PHP apps needing reliable ClickHouse access.
For large resultsets that don't fit in memory, use generators to process rows one at a time.
Streams results from ClickHouse using JSONEachRow format and yields one row at a time. Unlike select()->rows(), the full resultset is never loaded into PHP memory.
foreach ($db->selectGenerator('SELECT * FROM huge_table') as $row) {
// $row is an associative array: ['column1' => value1, 'column2' => value2, ...]
processRow($row);
}
foreach ($db->selectGenerator(
'SELECT * FROM events WHERE date > :date',
['date' => '2024-01-01']
) as $row) {
echo $row['event_name'] . "\n";
}
foreach ($db->selectGenerator(
'SELECT * FROM huge_table',
[],
['max_execution_time' => 600]
) as $row) {
// process with extended timeout
}
$count = 0;
foreach ($db->selectGenerator('SELECT * FROM events') as $row) {
$count++;
}
echo "Processed $count rows";
$fp = fopen('output.csv', 'w');
foreach ($db->selectGenerator('SELECT id, name, email FROM users') as $row) {
fputcsv($fp, $row);
}
fclose($fp);
If you already have a Statement from select(), you can iterate over it with a generator instead of calling rows():
$st = $db->select('SELECT * FROM table LIMIT 1000');
// Instead of $st->rows() which returns the full array:
foreach ($st->rowsGenerator() as $row) {
echo $row['id'] . "\n";
}
Note: rowsGenerator() still loads data in init() first. For true streaming from ClickHouse, use selectGenerator().
| Method | Memory | Speed | Use case |
|---|---|---|---|
select()->rows() |
All rows in memory | Fast for small results | < 100K rows |
select()->rowsGenerator() |
All rows in memory (init) | Iterator interface | When you need Generator type |
selectGenerator() |
One row at a time | Best for large results | > 100K rows, ETL, exports |
php://temp streamstreamRead() with FORMAT JSONEachRowThe key difference from select(): JSONEachRow format produces one JSON object per line, so each line can be decoded independently without parsing the entire response.
How can I help you explore Laravel packages today?