Skip to content

Commit d304e68

Browse files
authored
Add info about behavior methods proxying (#8378)
Refs cakephp/cakephp#19713
1 parent 2ebf996 commit d304e68

4 files changed

Lines changed: 62 additions & 33 deletions

File tree

‎docs/en/appendices/6-0-migration-guide.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ deprecation warnings.
2222
allowing listeners to register providers used by `Validator::add()`. Listeners
2323
that inspect rules added by `validationDefault()` must account for this order.
2424

25+
- Calling behavior methods directly on the table instance is now opt-in.
26+
Behaviors no longer expose their public methods as mixin methods on the
27+
table unless they are attached with the `implementedMethods` configuration
28+
set to `true`, a map of `alias => method` pairs, or a list of method names.
29+
2530
## Breaking Changes
2631

2732
### Renamed Methods

‎docs/en/orm/behaviors.md‎

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -96,62 +96,74 @@ Public methods on behaviors can be called as normal methods:
9696
$articles->getBehavior('Sluggable')->slug($value);
9797
```
9898

99-
Public methods defined on behaviors are also added as 'mixin' methods on the
100-
table object they are attached to. If you attach two behaviors that provide the
101-
same methods an exception will be raised. If a behavior provides the same method
102-
as a table class, the behavior method will not be callable from the table.
103-
Behavior mixin methods will receive the exact same arguments that are provided
104-
to the table. For example, if our SluggableBehavior defined the following
105-
method:
99+
Public methods defined on behaviors can also be exposed as 'mixin' methods on
100+
the table object they are attached to, so they can be called directly on the
101+
table. For example, if our SluggableBehavior defined the following method:
106102

107103
```php
108104
public function slug(string $value): string
109105
{
110-
return Text::slug($value, $this->_config['replacement']);
106+
return Text::slug($value, $this->getConfig('replacement'));
111107
}
112108
```
113109

114-
It could be invoked using:
110+
::: info Changed in version 6.0
111+
Exposing behavior methods on the table instance is opt-in. In 5.x all public
112+
behavior methods were proxied by default. In 6.0 nothing is proxied until you
113+
set the `implementedMethods` configuration key when attaching the behavior.
114+
:::
115+
116+
To proxy all of a behavior's public methods, set `implementedMethods` to
117+
`true` when adding the behavior:
118+
119+
```php
120+
// In a table's initialize() method.
121+
$this->addBehavior('Sluggable', [
122+
'implementedMethods' => true,
123+
]);
124+
```
125+
126+
The method could then be invoked using:
115127

116128
```php
117129
$slug = $articles->slug('My article');
118130
```
119131

120-
::: info Deprecated in version 5.3.0
121-
Calling behavior methods as mixin methods is deprecated
122-
:::
132+
If you attach two behaviors that provide the same method an
133+
exception will be raised. If a behavior provides the same method as a table
134+
class, the behavior method will not be callable from the table.
123135

124136
#### Limiting or Renaming Exposed Mixin Methods
125137

126-
When creating behaviors, there may be situations where you don't want to expose
127-
public methods as mixin methods. In these cases you can use the
128-
`implementedMethods` configuration key to rename or exclude mixin methods. For
129-
example if we wanted to prefix our slug() method we could do the following:
138+
When creating behaviors, there may be situations where you don't want to
139+
expose all public methods as mixin methods. Instead of setting
140+
`implementedMethods` to `true`, you can provide an array that maps the mixin
141+
method name to the behavior method it proxies. Providing an array both
142+
enables proxying and decides which methods are exposed. For example if we
143+
wanted to prefix our slug() method we could do the following when adding the
144+
behavior to a table:
130145

131146
```php
132-
protected array $_defaultConfig = [
147+
// In a table's initialize() method.
148+
$this->addBehavior('Sluggable', [
133149
'implementedMethods' => [
134150
'superSlug' => 'slug',
135151
]
136-
];
152+
]);
137153
```
138154

139155
Applying this configuration will make `slug()` not callable, however it will
140156
add a `superSlug()` mixin method to the table. Notably if our behavior
141157
implemented other public methods they would **not** be available as mixin
142158
methods with the above configuration.
143159

144-
Since the exposed methods are decided by configuration you can also
145-
rename/remove mixin methods when adding a behavior to a table. For example:
160+
The array can also be a numerically indexed list of method names, in which
161+
case each method is proxied under its own name, so
162+
`'implementedMethods' => ['slug']` is equivalent to
163+
`'implementedMethods' => ['slug' => 'slug']`.
146164

147-
```php
148-
// In a table's initialize() method.
149-
$this->addBehavior('Sluggable', [
150-
'implementedMethods' => [
151-
'superSlug' => 'slug',
152-
]
153-
]);
154-
```
165+
Method names are matched case-insensitively, and setting
166+
`implementedMethods` to an empty array disables mixin methods entirely.
155167

156168
### Defining Event Listeners
157169

@@ -173,7 +185,7 @@ use Cake\Utility\Text;
173185

174186
class SluggableBehavior extends Behavior
175187
{
176-
protected array $_defaultConfig = [
188+
protected array $defaultConfig = [
177189
'field' => 'title',
178190
'slug' => 'slug',
179191
'replacement' => '-',
@@ -247,7 +259,7 @@ or exclude finder methods. For example if we wanted to rename our `find(slug)`
247259
method we could do the following:
248260

249261
```php
250-
protected array $_defaultConfig = [
262+
protected array $defaultConfig = [
251263
'implementedFinders' => [
252264
'slugged' => 'findSlug',
253265
]
@@ -317,6 +329,10 @@ $table->behaviors()->has('CounterCache');
317329
// Get a loaded behavior
318330
// Remember to omit plugin prefixes
319331
$table->behaviors()->get('CounterCache');
332+
333+
// Check if any loaded behavior exposes a mixin method.
334+
// Only methods enabled through the `implementedMethods` config match.
335+
$table->behaviors()->hasMethod('slug');
320336
```
321337

322338
### Re-configuring Loaded Behaviors

‎docs/en/orm/behaviors/tree.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,15 @@ already holding some rows:
6666
```php
6767
// In a controller
6868
$categories = $this->getTableLocator()->get('Categories');
69-
$categories->recover();
69+
$categories->getBehavior('Tree')->recover();
7070
```
7171

72+
> [!NOTE]
73+
> `recover()` is a method provided by the `TreeBehavior`. Behavior methods are
74+
> only callable on the table instance when the behavior has been attached with
75+
> the `implementedMethods` configuration enabled, see
76+
> [Calling behavior methods](../../orm/behaviors#calling-behavior-methods).
77+
7278
You can verify it works by getting any row from the table and asking for the
7379
count of descendants it has:
7480

‎docs/en/orm/validation.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,10 @@ contain the validation rules declared in the `default` set.
201201
Validation rules can use functions defined on any known providers. By default
202202
CakePHP sets up a few providers:
203203

204-
1. Methods on the table class or its behaviors are available on the `table`
205-
provider.
204+
1. Methods on the table class are available on the `table` provider. Methods
205+
provided by behaviors are available on this provider as well, but only
206+
when the behavior is attached with the `implementedMethods` configuration
207+
enabled, see [Calling behavior methods](../orm/behaviors#calling-behavior-methods).
206208
2. The core `Cake\Validation\Validation` class is setup as the
207209
`default` provider.
208210

0 commit comments

Comments
 (0)