From f367ec92a4a856744f9f6f4353e5d5ceded54d3d Mon Sep 17 00:00:00 2001 From: mscherer Date: Sat, 11 Apr 2026 20:07:01 +0200 Subject: [PATCH] Document FunctionsBuilder::stringAgg() Adds documentation for the new portable stringAgg() method, covering per-driver translation and supported ordering. --- docs/en/appendices/5-4-migration-guide.md | 3 ++ docs/en/orm/query-builder.md | 37 +++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/docs/en/appendices/5-4-migration-guide.md b/docs/en/appendices/5-4-migration-guide.md index d350869cf4..5cce72220e 100644 --- a/docs/en/appendices/5-4-migration-guide.md +++ b/docs/en/appendices/5-4-migration-guide.md @@ -98,6 +98,9 @@ version is reported as `unknown`), the header is omitted. See [Query Builder](../orm/query-builder#advanced-conditions). - Added `inOrNull()` and `notInOrNull()` methods for combining `IN` conditions with `IS NULL`. - Added `isDistinctFrom()` and `isNotDistinctFrom()` methods for null-safe comparisons. +- Added `FunctionsBuilder::stringAgg()` for portable string aggregation. + Translates to `STRING_AGG` or `GROUP_CONCAT` per driver. + See [Query Builder](../orm/query-builder#string-aggregation). - Added PostgreSQL index access method reflection. Non-btree indexes (`gin`, `gist`, `spgist`, `brin`, `hash`) are now reflected with an `accessMethod` field and regenerated with the correct `USING` clause. The `Index` class diff --git a/docs/en/orm/query-builder.md b/docs/en/orm/query-builder.md index bb5215dd9f..027ec5e279 100644 --- a/docs/en/orm/query-builder.md +++ b/docs/en/orm/query-builder.md @@ -360,6 +360,11 @@ Calculate the max of a column. `Assumes arguments are literal values.` `count()` Calculate the count. `Assumes arguments are literal values.` +`stringAgg()` +Aggregate string values using a separator. Translates to `STRING_AGG()`, +`GROUP_CONCAT()`, or `LISTAGG()` depending on the database driver. +`Assumes the first argument is a literal value.` + `cast()` Convert a field or expression from one data type to another. @@ -471,6 +476,38 @@ FROM articles; > [!NOTE] > Use `func()` to pass untrusted user data to any SQL function. +#### String Aggregation + +The `stringAgg()` method provides a portable way to aggregate string values +using a separator. It translates to the appropriate native SQL function for +each driver (`STRING_AGG()` on PostgreSQL and SQL Server, `GROUP_CONCAT()` on +MySQL, and `STRING_AGG()` or `GROUP_CONCAT()` on MariaDB/SQLite depending on +version): + +```php +$query = $articles->find(); +$query->select([ + 'category_id', + 'titles' => $query->func()->stringAgg('title', ', '), +]) +->groupBy('category_id'); +``` + +You can optionally specify an ordering for the aggregated values via the +third argument: + +```php +$query->func()->stringAgg('title', ', ', ['title' => 'ASC']); +``` + +`STRING_AGG` with aggregate-local ordering is supported on PostgreSQL, +SQL Server, MariaDB 10.5+ and SQLite 3.44+. MySQL translates the call to +`GROUP_CONCAT` in all cases. + +::: info Added in version 5.4.0 +`FunctionsBuilder::stringAgg()` was added. +::: + ### Ordering Results To apply ordering, you can use the `orderBy()` method: