Skip to content

Commit f326d2b

Browse files
committed
Move detailed docs to actual documentation pages
Migration guide now contains concise entries with links. Detailed documentation added to: - controllers/components.md: Component alias conflicts section - controllers/request-response.md: Hypermedia Links (PSR-13) section - core-libraries/collections.md: keys(), values(), implode(), when(), unless() methods
1 parent 57b209a commit f326d2b

4 files changed

Lines changed: 201 additions & 67 deletions

File tree

docs/en/appendices/5-4-migration-guide.md

Lines changed: 6 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,8 @@ explicitly set `'strategy' => 'select'` when defining associations.
2929

3030
### Controller
3131

32-
When loading a component that has the same alias as the controller's default table,
33-
CakePHP now triggers a warning. This helps identify situations where accessing
34-
`$this->ComponentAlias` returns the table instead of the component:
35-
36-
```php
37-
class PaymentsController extends AppController
38-
{
39-
public function initialize(): void
40-
{
41-
parent::initialize();
42-
// Triggers warning: Component alias `Payments` clashes with the default table name
43-
$this->loadComponent('Payments');
44-
}
45-
}
46-
```
47-
48-
To resolve this, either use a different component alias or set `Controller::$defaultTable`
49-
to an empty string if the controller doesn't use a table.
32+
Loading a component with the same alias as the controller's default table now
33+
triggers a warning. See [Component Alias Conflicts](../controllers/components#component-alias-conflicts).
5034

5135
## Deprecations
5236

@@ -85,26 +69,7 @@ to an empty string if the controller doesn't use a table.
8569

8670
- Added PSR-13 Link implementation with `Cake\Http\Link\Link` and `Cake\Http\Link\LinkProvider`
8771
classes for hypermedia link support. Links added to responses are automatically emitted
88-
as HTTP `Link` headers.
89-
90-
```php
91-
use Cake\Http\Link\Link;
92-
93-
// Add links to a response
94-
$response = $response->withLink(new Link('/api/users', 'self'));
95-
$response = $response->withLink(
96-
(new Link('/api/users?page=2'))
97-
->withRel('next')
98-
->withAttribute('type', 'application/json'),
99-
);
100-
101-
// Preload resources
102-
$response = $response->withLink(
103-
(new Link('/css/app.css'))
104-
->withRel('preload')
105-
->withAttribute('as', 'style'),
106-
);
107-
```
72+
as HTTP `Link` headers. See [Hypermedia Links](../controllers/request-response#hypermedia-links).
10873

10974
### Utility
11075

@@ -114,26 +79,9 @@ $response = $response->withLink(
11479

11580
### Collection
11681

117-
- Added `keys()` method to return a collection containing only the keys.
118-
- Added `values()` method to return a collection of values re-indexed with consecutive integers.
119-
- Added `implode()` method to concatenate elements into a string, with optional path extraction.
120-
- Added `when()` and `unless()` methods for conditional method chaining.
121-
122-
```php
123-
// keys() and values()
124-
$collection = new Collection(['a' => 1, 'b' => 2]);
125-
$collection->keys()->toList(); // ['a', 'b']
126-
$collection->values()->toList(); // [1, 2]
127-
128-
// implode() with path extraction
129-
$collection = new Collection([['name' => 'foo'], ['name' => 'bar']]);
130-
$collection->implode(', ', 'name'); // 'foo, bar'
131-
132-
// Conditional chaining with when() and unless()
133-
$collection = new Collection($items)
134-
->when($shouldFilter, fn($c) => $c->filter(fn($v) => $v['active']))
135-
->unless($hasDefaults, fn($c) => $c->append($defaults));
136-
```
82+
- Added [`keys()`](../core-libraries/collections#keys) and [`values()`](../core-libraries/collections#values) methods for extracting keys or re-indexing values.
83+
- Added [`implode()`](../core-libraries/collections#implode) method to concatenate elements into a string.
84+
- Added [`when()`](../core-libraries/collections#when) and [`unless()`](../core-libraries/collections#unless) methods for conditional method chaining.
13785

13886
### View
13987

docs/en/controllers/components.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,47 @@ class MyFlashComponent extends FlashComponent
9898
The above would *alias* `MyFlashComponent` to `$this->Flash` in your
9999
controllers.
100100

101+
### Component Alias Conflicts
102+
103+
When a component alias matches the controller's default table name, accessing
104+
that property will return the table instead of the component. CakePHP triggers
105+
a warning when this conflict is detected:
106+
107+
```php
108+
class PaymentsController extends AppController
109+
{
110+
public function initialize(): void
111+
{
112+
parent::initialize();
113+
// Warning: Component alias `Payments` clashes with the default table name
114+
$this->loadComponent('Payments');
115+
}
116+
117+
public function index()
118+
{
119+
// This returns PaymentsTable, not PaymentsComponent!
120+
$this->Payments;
121+
}
122+
}
123+
```
124+
125+
To resolve this conflict, either use a different component alias:
126+
127+
```php
128+
$this->loadComponent('Payments', ['className' => 'Payments', 'alias' => 'PaymentService']);
129+
// Access via $this->PaymentService
130+
```
131+
132+
Or set `Controller::$defaultTable` to an empty string if the controller doesn't
133+
need a default table:
134+
135+
```php
136+
class PaymentsController extends AppController
137+
{
138+
protected ?string $defaultTable = '';
139+
}
140+
```
141+
101142
> [!NOTE]
102143
> Aliasing a component replaces that instance anywhere that component is used,
103144
> including inside other Components.

docs/en/controllers/request-response.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,61 @@ You can now use the convenience method
817817
`Cake\Http\Response::withLocation()` to directly set or get the
818818
redirect location header.
819819

820+
### Hypermedia Links
821+
822+
`method` Cake\\Http\\Response::**withLink**(LinkInterface $link): static
823+
824+
CakePHP implements [PSR-13](https://www.php-fig.org/psr/psr-13/) for hypermedia
825+
link support. You can add links to responses, and they will be automatically
826+
emitted as HTTP `Link` headers when the response is sent:
827+
828+
```php
829+
use Cake\Http\Link\Link;
830+
831+
// Add a simple link
832+
$response = $response->withLink(new Link('/api/users/1', 'self'));
833+
834+
// Add a link with multiple relations and attributes
835+
$response = $response->withLink(
836+
(new Link('/api/users?page=2'))
837+
->withRel('next')
838+
->withAttribute('type', 'application/json'),
839+
);
840+
841+
// Preload resources for performance
842+
$response = $response->withLink(
843+
(new Link('/css/app.css'))
844+
->withRel('preload')
845+
->withAttribute('as', 'style'),
846+
);
847+
```
848+
849+
The `Link` class implements `EvolvableLinkInterface` and provides these methods:
850+
851+
- `withHref(string $href)` - Set the link URI
852+
- `withRel(string $rel)` - Add a link relation
853+
- `withoutRel(string $rel)` - Remove a link relation
854+
- `withAttribute(string $name, $value)` - Add an attribute
855+
- `withoutAttribute(string $name)` - Remove an attribute
856+
857+
You can also work with multiple links using `LinkProvider`:
858+
859+
```php
860+
use Cake\Http\Link\Link;
861+
use Cake\Http\Link\LinkProvider;
862+
863+
$provider = new LinkProvider([
864+
new Link('/api/users/1', 'self'),
865+
new Link('/api/users?page=2', 'next'),
866+
]);
867+
868+
// Get the link provider from a response
869+
$links = $response->getLinks();
870+
871+
// Set a new link provider
872+
$response = $response->withLinkProvider($provider);
873+
```
874+
820875
### Setting the Body
821876

822877
`method` Cake\\Http\\Response::**withStringBody**(?string $string): static

docs/en/core-libraries/collections.md

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,17 @@ application as well.
6161
| `contains` | `countBy` | `each` |
6262
| `every` | `extract` | `filter` |
6363
| `first` | `firstMatch` | `groupBy` |
64-
| `indexBy` | `insert` | `isEmpty` |
65-
| `last` | `listNested` | `map` |
66-
| `match` | `max` | `median` |
67-
| `min` | `nest` | `prepend` |
68-
| `prependItem` | `reduce` | `reject` |
69-
| `sample` | `shuffle` | `skip` |
70-
| `some` | `sortBy` | `stopWhen` |
71-
| `sumOf` | `take` | `through` |
72-
| `transpose` | `unfold` | `zip` |
64+
| `implode` | `indexBy` | `insert` |
65+
| `isEmpty` | `keys` | `last` |
66+
| `listNested` | `map` | `match` |
67+
| `max` | `median` | `min` |
68+
| `nest` | `prepend` | `prependItem`|
69+
| `reduce` | `reject` | `sample` |
70+
| `shuffle` | `skip` | `some` |
71+
| `sortBy` | `stopWhen` | `sumOf` |
72+
| `take` | `through` | `transpose` |
73+
| `unfold` | `unless` | `values` |
74+
| `when` | `zip` | |
7375

7476
## Iterating
7577

@@ -1431,3 +1433,91 @@ foreach ($ages as $age) {
14311433
}
14321434
}
14331435
```
1436+
1437+
## Transforming Keys and Values
1438+
1439+
### keys()
1440+
1441+
`method` Cake\\Collection\\Collection::**keys**(): CollectionInterface
1442+
1443+
Returns a new collection containing only the keys from the original collection:
1444+
1445+
```php
1446+
$collection = new Collection(['a' => 1, 'b' => 2, 'c' => 3]);
1447+
$keys = $collection->keys()->toList(); // ['a', 'b', 'c']
1448+
```
1449+
1450+
### values()
1451+
1452+
`method` Cake\\Collection\\Collection::**values**(): CollectionInterface
1453+
1454+
Returns a new collection of values re-indexed with consecutive integers,
1455+
discarding the original keys:
1456+
1457+
```php
1458+
$collection = new Collection(['a' => 1, 'b' => 2, 'c' => 3]);
1459+
$values = $collection->values()->toList(); // [1, 2, 3]
1460+
```
1461+
1462+
## String Operations
1463+
1464+
### implode()
1465+
1466+
`method` Cake\\Collection\\Collection::**implode**(string $glue, callable|string|null $path = null): string
1467+
1468+
Concatenates all elements in the collection into a string, separated by
1469+
the given glue string. Optionally extract values using a path before joining:
1470+
1471+
```php
1472+
$collection = new Collection(['a', 'b', 'c']);
1473+
echo $collection->implode(', '); // 'a, b, c'
1474+
1475+
// With path extraction
1476+
$collection = new Collection([
1477+
['name' => 'Alice'],
1478+
['name' => 'Bob'],
1479+
['name' => 'Charlie'],
1480+
]);
1481+
echo $collection->implode(', ', 'name'); // 'Alice, Bob, Charlie'
1482+
1483+
// With a callback
1484+
$collection = new Collection([1, 2, 3]);
1485+
echo $collection->implode(' + ', fn($n) => $n * 2); // '2 + 4 + 6'
1486+
```
1487+
1488+
## Conditional Operations
1489+
1490+
### when()
1491+
1492+
`method` Cake\\Collection\\Collection::**when**(mixed $condition, callable $callback): CollectionInterface
1493+
1494+
Conditionally applies a callback to the collection when the condition is truthy.
1495+
This enables fluent conditional chaining without breaking the method chain:
1496+
1497+
```php
1498+
$collection = new Collection($items)
1499+
->when($shouldFilter, function ($collection) {
1500+
return $collection->filter(fn($item) => $item['active']);
1501+
})
1502+
->when($sortByName, function ($collection) {
1503+
return $collection->sortBy('name');
1504+
});
1505+
```
1506+
1507+
If the condition is falsy, the collection is returned unchanged.
1508+
1509+
### unless()
1510+
1511+
`method` Cake\\Collection\\Collection::**unless**(mixed $condition, callable $callback): CollectionInterface
1512+
1513+
The inverse of `when()`. Conditionally applies a callback to the collection
1514+
when the condition is falsy:
1515+
1516+
```php
1517+
$collection = new Collection($items)
1518+
->unless($hasDefaults, function ($collection) use ($defaults) {
1519+
return $collection->append($defaults);
1520+
});
1521+
```
1522+
1523+
If the condition is truthy, the collection is returned unchanged.

0 commit comments

Comments
 (0)