Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/en/appendices/5-4-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ See [Application and Plugin Events](../core-libraries/events#registering-event-l

- The `Mailer::$name` property is unused and has been deprecated.

### ORM

- `SelectQuery::disableHydration()` has been deprecated. Use
[`Table::findUnhydrated()`](../orm/retrieving-data-and-resultsets#getting-arrays-instead-of-entities)
instead, which returns a `SelectUnhydratedQuery` whose static type matches the
array result shape. `disableHydration()` will be removed in 6.0.

## New Features

### Core
Expand Down Expand Up @@ -172,6 +179,11 @@ See [Application and Plugin Events](../core-libraries/events#registering-event-l
- The `associated` option in `newEntity()` and `patchEntity()` now supports
nested array format matching `contain()` syntax.
See [Converting Request Data into Entities](../orm/saving-data#converting-request-data-into-entities).
- Added `Table::findUnhydrated()` and the `SelectUnhydratedQuery` class for
type-safe non-hydrated reads. Unlike `find()->disableHydration()`, the
returned query's static type matches its array result shape, so static
analyzers no longer see `entity|array` on `first()`, `all()`, `toArray()`
and iteration. See [Getting Arrays Instead of Entities](../orm/retrieving-data-and-resultsets#getting-arrays-instead-of-entities).

### Testsuite

Expand Down
52 changes: 40 additions & 12 deletions docs/en/orm/retrieving-data-and-resultsets.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,46 @@ you can pass query objects to your controllers, we recommend that you package
your queries up as [Custom Find Methods](#custom-find-methods) instead. Using custom finder
methods will let you re-use your queries and make testing easier.

By default, queries and result sets will return [Entities](../orm/entities) objects. You
can retrieve basic arrays by disabling hydration:
<a id="getting-arrays-instead-of-entities"></a>

### Getting Arrays Instead of Entities

By default, queries and result sets return [Entities](../orm/entities) objects.
When you only need plain arrays, use `findUnhydrated()` instead of `find()`:

```php
$query->disableHydration();
$query = $articles->findUnhydrated();

// $data is ResultSet that contains array data.
// $data is a ResultSet that contains array data.
$data = $query->all();

// Terminal methods are typed as arrays too.
$row = $articles->findUnhydrated()->where(['id' => 1])->first(); // array<string, mixed>|null
```

`findUnhydrated()` accepts the same finder type and arguments as `find()`, so
your existing [custom finders](#custom-find-methods) are reused unchanged:

```php
$rows = $articles->findUnhydrated('published')->all();
```

It returns a `Cake\ORM\Query\SelectUnhydratedQuery`. This behaves exactly like
`find()->disableHydration()` at runtime, but its static type matches the array
result shape, so static analyzers no longer see `entity|array` on `first()`,
`firstOrFail()`, `all()`, `toArray()` and iteration — including after the query
flows through a custom finder.

> [!NOTE]
> `findUnhydrated()` only changes the result shape for row-returning finders.
> `findList()` and `findThreaded()` produce a key/value map or nested tree
> regardless of hydration, so there is nothing to type differently for them.

> [!WARNING]
> `SelectQuery::disableHydration()` is deprecated as of 5.4.0 and will be
> removed in 6.0. The fluent toggle returns a query whose static type still
> claims to produce entities; prefer `findUnhydrated()` instead.

<a id="table-find-first"></a>

## Getting the First Result
Expand Down Expand Up @@ -1071,15 +1101,15 @@ section show how you can add calculated fields, or replace the result set.
> ->all();
> ```
>
> Depending on your use case, you may also consider using disabling hydration:
> Depending on your use case, you may also consider skipping hydration:
>
> ``` bash
> $results = $articles->find()
> ->disableHydration()
> $results = $articles->findUnhydrated()
> ->all();
> ```
>
> The above will disable creation of entity objects and return rows as arrays instead.
> The above will skip creation of entity objects and return rows as arrays instead.
> See [Getting Arrays Instead of Entities](#getting-arrays-instead-of-entities).

### Getting the First & Last Record From a ResultSet

Expand Down Expand Up @@ -1244,10 +1274,9 @@ $reducer = function ($occurrences, $word, $mapReduce) {
Finally, we put everything together:

```php
$wordCount = $articles->find()
$wordCount = $articles->findUnhydrated()
->where(['published' => true])
->andWhere(['published_date >=' => new DateTime('2014-01-01')])
->disableHydration()
->mapReduce($mapper, $reducer)
->all()
->toArray();
Expand Down Expand Up @@ -1317,8 +1346,7 @@ $reducer = function ($friends, $user, $mr) {
And we supply our functions to a query:

```php
$fakeFriends = $friends->find()
->disableHydration()
$fakeFriends = $friends->findUnhydrated()
->mapReduce($mapper, $reducer)
->all()
->toArray();
Expand Down