You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This software provides an object oriented convention around [Parameter](https://chevere.org/packages/parameter).
5
+
Action implements the Action Design Pattern (a variant of the Command Pattern) that encapsulates operations as reusable, self-validating objects. Built on the [Parameter](https://github.com/chevere/parameter) library, it provides a robust framework for defining business logic with strict input/output validation, promoting type safety and reducing boilerplate code across your application.
Implement ActionInterface by using the [Action trait](#use-actiontrait) or by extending [Action abstract](#extend-action).
18
-
19
-
## Creating actions
17
+
To create an Action class implement the [ActionInterface](https://github.com/chevere/action/blob/2.1/src/Interfaces/ActionInterface.php) either with [use ActionTrait](#use-actiontrait) or by [extends Action](#extends-action).
20
18
21
19
### Use ActionTrait
22
20
23
-
Create an action by using ActionTrait.
21
+
To create an action by using [ActionTrait](https://github.com/chevere/action/blob/2.1/src/Traits/ActionTrait.php):
24
22
25
23
```php
26
24
use Chevere\Action\Interfaces\ActionInterface;
@@ -33,9 +31,9 @@ class MyAction implements ActionInterface
33
31
}
34
32
```
35
33
36
-
### Extend Action
34
+
### Extends Action
37
35
38
-
Create an Action by extending Action.
36
+
To create an Action by extending [Action](https://github.com/chevere/action/blob/2.1/src/Action.php):
39
37
40
38
```php
41
39
use Chevere\Action\Action;
@@ -46,16 +44,16 @@ class MyAction extends Action
46
44
}
47
45
```
48
46
49
-
##Main method
47
+
### Invoke method
50
48
51
-
Use the `main` method to determine your action's main logic. Use **attributes** from [chevere/parameter](https://github.com/chevere/parameter) on arguments and method return to add validation rules.
49
+
Use the `__invoke()` method to determine action main logic. Use **attributes** from [chevere/parameter](https://github.com/chevere/parameter) on both parameters and return to add assertion rules.
52
50
53
-
* Before validation rules:
51
+
* Before assertion rules:
54
52
55
53
```php
56
54
class MyAction
57
55
{
58
-
protected function main(
56
+
public function __invoke(
59
57
string $value
60
58
): int
61
59
{
@@ -64,7 +62,7 @@ class MyAction
64
62
}
65
63
```
66
64
67
-
* After validation rules:
65
+
* After assertion rules:
68
66
69
67
```php
70
68
use Chevere\Action\Action;
@@ -77,123 +75,223 @@ class MyAction extends Action
77
75
#[ReturnAttr(
78
76
new IntAttr(min: 0, max: 100)
79
77
)]
80
-
protected function main(
78
+
public function __invoke(
81
79
#[StringAttr('/^ok/')]
82
80
string $value
83
81
): int {
84
-
return mb_strlen($value) * 5;
82
+
$this->assertArguments($value);
83
+
return $this->assertReturn(
84
+
mb_strlen($value) * 5
85
+
);
85
86
}
86
87
}
87
88
```
88
89
89
-
## Using actions
90
+
The code above demonstrates how to create an Action class with input validation and output assertion. The `$value` argument must match the regular expression `/^ok/` and the return value must be an integer between 0 and 100. See Advanced use for alternative approaches.
91
+
92
+
## Using Action
90
93
91
-
Invoke action's main logic passing the arguments you would pass to `main`. Action internal runtime will validate arguments and return against all defined rules.
94
+
### Invoking Actions
92
95
93
-
💡 You can toy with this by running `php demo/demo.php`
96
+
Invoke action's `__invoke()` method, same as a function. Action internal runtime will assert arguments and return against your expectations.
97
+
98
+
💡 You can try by running `php demo/demo.php`
94
99
95
100
```php
96
101
$action = new MyAction();
97
-
$result = $action('ok muy bueno');
102
+
$result = $action->__invoke('ok muy bueno');
103
+
$result = $action('ok muy bueno'); // same thing
104
+
```
105
+
106
+
### ActionName
107
+
108
+
Actions can use the `public function setUp(...)` method to define logic which must be executed before the Action is invoked.
109
+
110
+
For example, an Action may define to require setup location and code arguments:
111
+
112
+
```php
113
+
use Chevere\Action\Action;
114
+
115
+
class Redirect extends Action
116
+
{
117
+
public function setUp(string $location, int $code): void
118
+
{
119
+
$this->location = $location;
120
+
$this->code = $code;
121
+
}
122
+
}
123
+
```
124
+
125
+
With `ActionName` you can store the Action name and its `setUp()` arguments:
126
+
127
+
```php
128
+
use Chevere\Action\ActionName;
129
+
130
+
$actionName = new ActionName(Redirect::class, $location, $code);
131
+
```
132
+
133
+
Which you can later use directly:
134
+
135
+
```php
136
+
$className = (string) $actionName;
137
+
$action = new $className();
138
+
$action->setUp(...$actionName->arguments());
139
+
```
140
+
141
+
Or craft your own `ActionName` accessors directly on your Actions:
142
+
143
+
```php
144
+
use Chevere\Action\Action;
145
+
use Chevere\Action\ActionName;
146
+
use Chevere\Action\Interfaces\ActionNameInterface;
147
+
148
+
class Redirect extends Action
149
+
{
150
+
// setUp(...)
151
+
152
+
public static function with(string $location, int $code): ActionNameInterface
153
+
{
154
+
return new ActionName(static::class, ...get_defined_vars());
155
+
}
156
+
}
157
+
```
158
+
159
+
Which you can later use like this:
160
+
161
+
```php
162
+
$redirect = Redirect::with('some/location', 302);
98
163
```
99
164
100
165
## Advanced use
101
166
102
-
### Return method
167
+
This library offers flexible validation strategies to match your application's architecture. While embedding assertions within the `__invoke()` method provides maximum portability, you can also implement centralized validation logic or delegate validation responsibilities to callers. The following methods enable fine-grained control over where and how validations are performed across.
168
+
169
+
### Accept return method
103
170
104
-
For validating `return` beyond the limitations of PHP's attributes you can define Action's `return()` method. In this context you can use and remix any [Parameter function](https://github.com/chevere/parameter#function-reference).
171
+
Use method `acceptReturn()` to define return value assertion rules. In this context you can use and remix any [Parameter function](https://github.com/chevere/parameter#function-reference).
172
+
173
+
**Note:** Attribute notation `#[ReturnAttr]` has greater precedence than `acceptReturn()`.
105
174
106
175
```php
107
176
use Chevere\Action\Interfaces\ParameterInterface;
108
177
use function Chevere\Parameter\string;
109
178
110
-
public static function return(): ParameterInterface
179
+
public static function acceptReturn(): ParameterInterface
111
180
{
112
181
return string();
113
182
}
114
183
```
115
184
116
-
You can also forward parameter resolution to a callable by using `CallableAttr`:
185
+
### Assert arguments method
186
+
187
+
Use method `assertArguments()` to assert Action's `__invoke()` arguments against your expectations. When `assertArguments()` method is called without arguments, it will magic take the arguments from the function caller context.
188
+
189
+
```php
190
+
// magic
191
+
$action->assertArguments();
192
+
// explicit
193
+
$action->assertArguments(...$args);
194
+
// explicit, all defined vars
195
+
$action->assertArguments(...get_defined_vars());
196
+
```
197
+
198
+
All the following sample definitions are equivalent in results and will evaluate the same arguments.
117
199
118
200
```php
119
-
use Chevere\Action\Attributes\CallableAttr;
120
-
use Chevere\Action\Attributes\ReturnAttr;
121
-
use function Chevere\Parameter\string;
201
+
public function __invoke($foo, $bar): void {
202
+
$this->assertArguments();
203
+
}
122
204
123
-
function myCallable(): StringParameterInterface
124
-
{
125
-
return string();
205
+
public function __invoke($foo, $bar): void {
206
+
$this->assertArguments($foo, $bar);
126
207
}
127
208
128
-
#[ReturnAttr(
129
-
new CallableAttr('myCallable')
130
-
)]
131
-
protected function main(): string
132
-
{
133
-
return 'chevere';
209
+
public function __invoke($foo, $bar): void {
210
+
$this->assertArguments(...get_defined_vars());
134
211
}
135
212
```
136
213
137
-
### Custom main method
214
+
### Assert return method
138
215
139
-
Override Action's `mainMethod` to define a custom `main` method to use.
216
+
Use method `assertReturn()` to assert Action's `__invoke()` return value against your expectations.
140
217
141
218
```php
142
-
public static function mainMethod(): string
143
-
{
144
-
return 'altMain';
145
-
}
219
+
$action->assertReturn($result);
146
220
```
147
221
148
-
##Controller
222
+
### Assert method
149
223
150
-
The Controller component is a special type of Action in charge of handling incoming instructions. Its `main` method only takes parameters of type `string`.
224
+
Use method `assert()` to assert runtime rules coherence.
151
225
152
-
Controller is intended to use them wired to:
226
+
```php
227
+
$action->assert();
228
+
```
153
229
154
-
* Web Servers
155
-
* CLI applications
156
-
* Application runners
230
+
### Reflection method
157
231
158
-
### Defining a Controller
232
+
Use method `reflection()` to access ReflectionAction instance. It enables to read Action's parameters and return assertion rules.
159
233
160
-
A Controller implements the `ControllerInterface`. You can extend `Controller` to quick create a compliant Controller:
234
+
```php
235
+
$action::reflection()->parameters();
236
+
$action::reflection()->return();
237
+
```
238
+
239
+
### Accept rules static method
240
+
241
+
This method is called before `assert*()` calls.
242
+
243
+
Use method `acceptRulesStatic()` to define additional static assertion rules to constrain your custom Action design. The purpose of this method is demonstrated at the [Controller class](https://github.com/chevere/action/blob/2.1/src/Controller.php) to constrain the design by restricting `__invoke()` parameters to type string.
244
+
245
+
This is very flexible and allows you to enforce advanced design rules at the class level and for very specific cases, for example to forbid certain parameter names:
161
246
162
247
```php
163
-
use Chevere\Action\Controller;
248
+
public static function acceptRulesStatic(): void {
throw new LogicException('Parameter $lucho is forbidden');
251
+
}
252
+
}
253
+
```
164
254
165
-
class SomeController extends Controller
255
+
### Accept rules runtime method
256
+
257
+
This method is called before `assert*()` calls.
258
+
259
+
Use method `acceptRulesRuntime()` to define additional runtime assertion rules. The purpose of this method is demonstrated at the [HTTP Controller](https://github.com/chevere/http) to constrain the design by ensuring the existence of HTTP participants.
260
+
261
+
```php
262
+
public function acceptRulesRuntime(): void
166
263
{
167
-
// ...
264
+
if (! isset($this->_query, $this->_bodyParsed, $this->_files)) {
265
+
throw new LogicException('Server request not set.');
266
+
}
168
267
}
169
268
```
170
269
171
-
### Main Parameters
270
+
##Controller
172
271
173
-
Parameters are defined in the `main` method but it just takes strings.
272
+
The Controller is a special type of Action in charge of handling command-like instructions. Its `__invoke()` method only takes parameters of type `string|int|float`.
273
+
274
+
### Defining a Controller
275
+
276
+
A Controller implements the `ControllerInterface`. You can extend `Controller` to quick create a compliant Controller:
174
277
175
278
```php
176
-
public function main(
177
-
string $pepito,
178
-
string $paysTwice
179
-
): array
279
+
use Chevere\Controller\Controller;
280
+
281
+
class SomeController extends Controller
180
282
{
181
283
// ...
182
284
}
183
285
```
184
286
185
-
##Parameter Attributes
287
+
### Invoke parameters
186
288
187
-
Use `StringAttr` to validate string:
289
+
Parameters are defined in the `__invoke()` method but it just takes type `string`, `int`, or `float`.
0 commit comments