@@ -18,30 +18,14 @@ bin/cake upgrade rector --rules cakephp54 <path/to/app/src>
1818
1919### I18n
2020
21- `` Number::parseFloat() `` now returns `` null `` instead of `` 0.0 `` when parsing
22- fails. Previously, when `` NumberFormatter::parse() `` failed it returned `` false `` ,
23- which was cast to `` 0.0 `` . This silently converted invalid input like `` "abc" ``
24- to `` 0.0 `` , making it impossible to distinguish from valid `` "0" `` input.
25-
26- This also affects `` FloatType `` and `` DecimalType `` database types which use
27- `` Number::parseFloat() `` internally. Invalid locale-formatted form input will
28- now result in `` null `` entity values instead of `` 0 `` .
21+ ` Number::parseFloat() ` now returns ` null ` instead of ` 0.0 ` when parsing
22+ fails. This also affects ` FloatType ` and ` DecimalType ` database types.
2923
3024### ORM
3125
3226The default eager loading strategy for ` HasMany ` and ` BelongsToMany ` associations
33- has changed from `` select `` to `` subquery `` . The `` subquery `` strategy performs
34- better for larger datasets as it avoids packet size limits from large `` WHERE IN ``
35- clauses and reduces PHP memory usage by keeping IDs in the database.
36-
37- If you need the previous behavior, you can explicitly set the strategy when
38- defining associations:
39-
40- ``` php
41- $this->hasMany('Comments', [
42- 'strategy' => 'select',
43- ]);
44- ```
27+ has changed from ` select ` to ` subquery ` . If you need the previous behavior,
28+ explicitly set ` 'strategy' => 'select' ` when defining associations.
4529
4630## Deprecations
4731
@@ -51,199 +35,38 @@ $this->hasMany('Comments', [
5135
5236### Controller
5337
54- #### RequestToDto Attribute
55-
56- A new `` #[RequestToDto] `` attribute enables automatic mapping of request data to
57- Data Transfer Objects in controller actions. This provides a clean way to handle
58- form data with type safety:
59-
60- ``` php
61- use Cake\Controller\Attribute\RequestToDto;
62-
63- class UsersController extends AppController
64- {
65- public function create(#[RequestToDto] UserCreateDto $dto): void
66- {
67- // $dto is automatically populated from request data
68- $user = $this->Users->newEntity([
69- 'email' => $dto->email,
70- 'name' => $dto->name,
71- ]);
72- }
73- }
74- ```
75-
76- Your DTO class must implement a static `` createFromArray() `` method:
77-
78- ``` php
79- class UserCreateDto
80- {
81- public function __construct(
82- public string $email,
83- public string $name,
84- ) {
85- }
86-
87- public static function createFromArray(array $data): self
88- {
89- return new self(
90- email: $data['email'] ?? '',
91- name: $data['name'] ?? '',
92- );
93- }
94- }
95- ```
96-
97- The attribute supports configuring the data source:
98-
99- ``` php
100- use Cake\Controller\Attribute\Enum\RequestToDtoSource;
101-
102- // Use query string parameters
103- public function search(
104- #[RequestToDto(source: RequestToDtoSource::Query)] SearchDto $dto
105- ): void {}
106-
107- // Use POST body data
108- public function create(
109- #[RequestToDto(source: RequestToDtoSource::Body)] CreateDto $dto
110- ): void {}
111-
112- // Merge query and body (body takes precedence)
113- public function update(
114- #[RequestToDto(source: RequestToDtoSource::Request)] UpdateDto $dto
115- ): void {}
116-
117- // Auto-detect based on request method (default)
118- public function handle(
119- #[RequestToDto(source: RequestToDtoSource::Auto)] DataDto $dto
120- ): void {}
121- ```
122-
123- #### FormProtection Convenience Methods
124-
125- `` FormProtectionComponent `` now has convenience methods for unlocking actions
126- and fields:
127-
128- ``` php
129- // In your controller's beforeFilter()
130- $this->FormProtection->unlockActions(['api', 'webhook']);
131- $this->FormProtection->unlockFields(['dynamic_field', 'optional_field']);
132-
133- // With merge option (default is true)
134- $this->FormProtection->unlockActions('newAction', merge: true);
135- $this->FormProtection->unlockFields(['field1', 'field2'], merge: false);
136- ```
38+ - Added ` #[RequestToDto] ` attribute for automatic mapping of request data to
39+ Data Transfer Objects in controller actions.
40+ See [ Request to DTO Mapping] ( ../development/dependency-injection#request-to-dto-mapping ) .
41+ - Added ` unlockActions() ` and ` unlockFields() ` convenience methods to
42+ ` FormProtectionComponent ` .
43+ See [ Form Protection Component] ( ../controllers/components/form-protection ) .
13744
13845### Database
13946
140- #### Query Expression Methods
141-
142- New convenience methods have been added to `` QueryExpression `` :
143-
144- - `` notBetween() `` for `` NOT BETWEEN `` expressions:
145-
146- ``` php
147- $query = $articles->find()
148- ->where(function (QueryExpression $exp) {
149- return $exp->notBetween('view_count', 100, 1000);
150- });
151- // WHERE view_count NOT BETWEEN 100 AND 1000
152- ```
153-
154- - `` inOrNull() `` for `` (field IN (...) OR field IS NULL) `` patterns:
155-
156- ``` php
157- $query = $articles->find()
158- ->where(function (QueryExpression $exp) {
159- return $exp->inOrNull('category_id', [1, 2, 3]);
160- });
161- // WHERE (category_id IN (1, 2, 3) OR category_id IS NULL)
162- ```
163-
164- - `` isDistinctFrom() `` and `` isNotDistinctFrom() `` for null-safe comparisons:
165-
166- ``` php
167- $query = $articles->find()
168- ->where(function (QueryExpression $exp) {
169- // True when values differ, treating NULL as a comparable value
170- return $exp->isDistinctFrom('status', 'published');
171- });
172- // WHERE status IS DISTINCT FROM 'published'
173- // MySQL uses: NOT (status <=> 'published')
174-
175- $query = $articles->find()
176- ->where(function (QueryExpression $exp) {
177- // True when values are equal, treating NULL = NULL as true
178- return $exp->isNotDistinctFrom('category_id', null);
179- });
180- // WHERE category_id IS NOT DISTINCT FROM NULL
181- // MySQL uses: category_id <=> NULL
182- ```
47+ - Added ` notBetween() ` method for ` NOT BETWEEN ` expressions.
48+ See [ Query Builder] ( ../orm/query-builder#advanced-conditions ) .
49+ - Added ` inOrNull() ` and ` notInOrNull() ` methods for combining ` IN ` conditions with ` IS NULL ` .
50+ - Added ` isDistinctFrom() ` and ` isNotDistinctFrom() ` methods for null-safe comparisons.
18351
18452### I18n
18553
186- - ` Number::toReadableSize() ` now calculates decimal units (KB, MB, GB and TB)
187- using an exponent of ten, meaning that 1 KB is 1000 Bytes. The units from the
188- previous calculation method, where 1024 Bytes equaled 1 KB, have been changed
189- to KiB, MiB, GiB, and TiB as defined in ISO/IEC 80000-13. It is possible to
190- switch between the two units using a new optional boolean parameter in
191- ` Number::toReadableSize() ` , as well as the new global setter ` Number::setUseIecUnits() ` .
54+ - ` Number::toReadableSize() ` now uses decimal units (KB = 1000 bytes) by default.
55+ Binary units (KiB = 1024 bytes) can be enabled via parameter or ` Number::setUseIecUnits() ` .
19256
19357### ORM
19458
195- #### Nested Array Format for Marshalling
196-
197- The `` associated `` option in `` newEntity() `` and `` patchEntity() `` now supports
198- the same nested array format as `` contain() `` :
199-
200- ``` php
201- // Nested arrays (new in 5.4)
202- $entity = $articles->newEntity($data, [
203- 'associated' => [
204- 'Tags',
205- 'Comments' => [
206- 'Users',
207- 'Attachments',
208- ],
209- ],
210- ]);
211-
212- // Mixed with options
213- $entity = $articles->newEntity($data, [
214- 'associated' => [
215- 'Tags' => ['onlyIds' => true],
216- 'Comments' => [
217- 'Users',
218- 'validate' => 'special',
219- ],
220- ],
221- ]);
222- ```
223-
224- CakePHP distinguishes associations from options using naming conventions:
225-
226- - Association names use PascalCase (e.g., `` Users `` , `` Comments `` )
227- - Option keys use camelCase (e.g., `` onlyIds `` , `` validate `` )
59+ - The ` associated ` option in ` newEntity() ` and ` patchEntity() ` now supports
60+ nested array format matching ` contain() ` syntax.
61+ See [ Converting Request Data into Entities] ( ../orm/saving-data#converting-request-data-into-entities ) .
22862
22963### Utility
23064
231- - New ` Cake\Utility\Fs\Finder ` class provides a fluent, iterator-based API for
232- discovering files and directories with support for pattern matching, depth
233- control, and custom filters. The ` Cake\Utility\Fs\Path ` class offers
234- cross-platform utilities for path manipulation.
65+ - Added ` Cake\Utility\Fs\Finder ` class for fluent file discovery with pattern matching,
66+ depth control, and custom filters. Added ` Cake\Utility\Fs\Path ` for cross-platform
67+ path manipulation.
23568
23669### View
23770
238- #### FormHelper Template Variables
239-
240- The `` inputContainer `` and `` error `` templates now receive an `` {{inputId}} ``
241- variable containing the input element's HTML id attribute. This is useful for
242- generating related element IDs for ARIA attributes or custom JavaScript:
243-
244- ``` php
245- $this->Form->setTemplates([
246- 'inputContainer' => '<div class =" input {{type}}{{required}}" id =" {{inputId}}-container" >{{content}}</div >',
247- 'error' => '<div class =" error" id =" {{inputId}}-error" >{{content}}</div >',
248- ]);
249- ```
71+ - Added ` {{inputId}} ` template variable to ` inputContainer ` and ` error ` templates
72+ in FormHelper. See [ Built-in Template Variables] ( ../views/helpers/form#built-in-template-variables ) .
0 commit comments