diff --git a/docs/en/orm/database-basics.md b/docs/en/orm/database-basics.md index 91a7875906..2c2ca64160 100644 --- a/docs/en/orm/database-basics.md +++ b/docs/en/orm/database-basics.md @@ -432,7 +432,6 @@ date value that is translated to the driver's dialect. `CURRENT_DATE` will also be used in relected schema metadata. - datetime : See [Datetime Type](#datetime-type). diff --git a/docs/en/orm/query-builder.md b/docs/en/orm/query-builder.md index bfefcb020d..efdcf109ae 100644 --- a/docs/en/orm/query-builder.md +++ b/docs/en/orm/query-builder.md @@ -390,6 +390,69 @@ Add the time unit to the date expression. `dayOfWeek()` Returns a FunctionExpression representing a call to SQL WEEKDAY function. +#### JSON Path Expressions + +::: info Added in version 5.5.0 +`JsonPathExpression` was added. +::: + +`JsonPathExpression` describes a path into a JSON document. `$` refers to the +root, `.price` selects a property, and `[0]` selects the first array element: + +```php +use Cake\Database\Expression\JsonPathExpression; + +$pricePath = new JsonPathExpression('$.price'); +$firstPricePath = new JsonPathExpression('$.prices[0]'); +``` + +The expression can also define SQL/JSON clauses. `returning()` sets the SQL +return type, `passing()` supplies named path variables, and `onEmpty()` and +`onError()` choose how missing values and errors are handled. Support depends +on the database function using the path: + +| Database | Optional clauses supported by `JSON_VALUE()` | +|---|---| +| [PostgreSQL 17+](https://www.postgresql.org/docs/17/functions-json.html#SQLJSON-QUERY-FUNCTIONS) | `PASSING`, `RETURNING`, `ON EMPTY`, `ON ERROR` | +| [MySQL 8.0.21+](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-value) | `RETURNING`, `ON EMPTY`, `ON ERROR` | +| [SQL Server 2025+](https://learn.microsoft.com/en-us/sql/t-sql/functions/json-value-transact-sql) | `RETURNING`, when the input uses the native `json` type | +| MariaDB, SQL Server 2022 and earlier, SQLite | None of these optional clauses | + +For example, PostgreSQL 17+ supports a variable selecting an array element, +with a numeric return type and fallback behavior: + +```php +$path = (new JsonPathExpression('$.prices[$idx]')) + ->passing(['idx' => 0]) + ->returning('numeric') + ->onEmpty(JsonPathExpression::BEHAVIOR_DEFAULT, 0) + ->onError(JsonPathExpression::BEHAVIOR_NULL); +``` + +`passing()` accepts a map of variable names to values and an optional map of +binding types. JSON paths and passing values are bound as parameters; SQL +returning types and variable names are not sanitized, so define those in +application code rather than taking them from request data. + +Clause support varies by database and version. PostgreSQL 17+ uses native +`JSON_VALUE()`. Earlier PostgreSQL versions retain the `JSONB_PATH_QUERY()` +translation, which is not equivalent to native scalar `JSON_VALUE()` and does +not support these optional clauses. SQLite translates it to `JSON_EXTRACT()`. + +#### JSON Functions + +`jsonValue()` +Extract a scalar value from a JSON column. Accepts a JSON path string or a +`JsonPathExpression`. For example, using the PostgreSQL path configured above: + +```php +$query = $articles->find(); +$query->select([ + 'category' => $query->func()->jsonValue('Articles.metadata', '$.category'), + 'price' => $query->func()->jsonValue('Articles.metadata', $path), +]); +``` + #### Window-Only Functions These window-only functions contain a window expression by default: