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
fix(docs): correct observer and plugin examples across all docs
- Observer: use #[Observer(event: Class::class)] attribute instead of
string event names or non-existent module.php 'observers' registration
- Plugins: use #[Plugin(target:)], #[Before], #[After] attributes
instead of non-existent module.php 'plugins' registration
- Fix plugin method signatures: no $subject param, before returns null,
after receives $result as first arg
- All examples now match the actual core implementation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/src/content/docs/concepts/events.md
+17-20Lines changed: 17 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,7 +58,7 @@ class PostCreatedEvent
58
58
59
59
## Creating Observers
60
60
61
-
An observer is a class that handles a specific event:
61
+
An observer is a class with the `#[Observer]` attribute that handles a specific event. The `event` parameter specifies which event class to listen for:
62
62
63
63
```php title="TrackPostCreation.php"
64
64
<?php
@@ -68,7 +68,9 @@ declare(strict_types=1);
68
68
namespace App\Analytics\Observer;
69
69
70
70
use Marko\Blog\Event\PostCreatedEvent;
71
+
use Marko\Core\Attributes\Observer;
71
72
73
+
#[Observer(event: PostCreatedEvent::class)]
72
74
class TrackPostCreation
73
75
{
74
76
public function handle(PostCreatedEvent $event): void
@@ -80,31 +82,26 @@ class TrackPostCreation
80
82
}
81
83
```
82
84
83
-
## Registering Observers
85
+
Observers are discovered automatically from module `src/` directories — no manual registration needed.
84
86
85
-
Observers are registered in `module.php`:
86
-
87
-
```php title="module.php"
88
-
<?php
87
+
## Observer Priority
89
88
90
-
declare(strict_types=1);
89
+
When multiple observers listen to the same event, they run by priority (higher values first). Use the `priority` parameter to control order:
public function handle(PostCreatedEvent $event): void { /* ... */ }
102
+
}
102
103
```
103
104
104
-
## Observer Priority
105
-
106
-
When multiple observers listen to the same event, they run in module priority order (`app/` → `modules/` → `vendor/`). Within the same module, observers run in the order they're listed.
107
-
108
105
## Built-in Events
109
106
110
107
Marko packages dispatch events at meaningful points:
Copy file name to clipboardExpand all lines: docs/src/content/docs/concepts/plugins.md
+26-30Lines changed: 26 additions & 30 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,7 +20,7 @@ Marko intentionally does **not** support Around plugins. Around plugins (which w
20
20
21
21
## Creating a Plugin
22
22
23
-
A plugin is a plain PHP class with methods that follow a naming convention:
23
+
A plugin is a class with the `#[Plugin]` attribute targeting the class you want to intercept. Methods use `#[Before]` and `#[After]` attributes and follow a naming convention:
24
24
25
25
```php title="PostRepositoryPlugin.php"
26
26
<?php
@@ -30,68 +30,64 @@ declare(strict_types=1);
30
30
namespace App\MyApp\Plugin;
31
31
32
32
use Marko\Blog\Repository\PostRepository;
33
+
use Marko\Core\Attributes\After;
34
+
use Marko\Core\Attributes\Before;
35
+
use Marko\Core\Attributes\Plugin;
33
36
37
+
#[Plugin(target: PostRepository::class)]
34
38
class PostRepositoryPlugin
35
39
{
36
40
/**
37
-
* Modify arguments before getPost() is called.
41
+
* Runs before getPost() — return null to continue, or non-null to short-circuit.
38
42
*/
39
-
public function beforeGetPost(PostRepository $subject, int $id): array
43
+
#[Before]
44
+
public function beforeGetPost(int $id): null
40
45
{
41
-
// Log or transform the input
42
-
return [$id]; // Return modified arguments as array
46
+
// Log or validate the input
47
+
return null;
43
48
}
44
49
45
50
/**
46
-
* Modify the return value after getPost() completes.
51
+
* Runs after getPost() — receives the result, then the original arguments.
47
52
*/
48
-
public function afterGetPost(PostRepository $subject, array $result): array
53
+
#[After]
54
+
public function afterGetPost(array $result, int $id): array
49
55
{
50
-
// Add extra data to the result
56
+
// Enrich the result
51
57
$result['retrieved_at'] = time();
52
58
53
59
return $result;
54
60
}
55
61
}
56
62
```
57
63
64
+
Plugins are discovered automatically from module `src/` directories — no manual registration needed.
65
+
58
66
### Method Naming
59
67
60
68
-`beforeMethodName` — runs before `methodName`
61
69
-`afterMethodName` — runs after `methodName`
62
70
63
-
The first parameter is always `$subject` (the original object). For `before` plugins, remaining parameters match the original method's signature. Return an array of the (possibly modified) arguments.
64
-
65
-
For `after` plugins, the second parameter is the result from the original method. Return the (possibly modified) result.
71
+
For `before` plugins, parameters match the original method's signature. Return `null` to continue to the original method, or return a non-null value to short-circuit and use that as the result.
66
72
67
-
## Registering Plugins
73
+
For `after` plugins, the first parameter is the result from the original method, followed by the original arguments. Return the (possibly modified) result.
68
74
69
-
Plugins are registered in `module.php`:
70
-
71
-
```php title="module.php"
72
-
<?php
75
+
### Sort Order
73
76
74
-
declare(strict_types=1);
75
-
76
-
use App\MyApp\Plugin\PostRepositoryPlugin;
77
-
use Marko\Blog\Repository\PostRepository;
77
+
Use the `sortOrder` parameter to control the order when multiple plugins target the same method:
78
78
79
-
return [
80
-
'plugins' => [
81
-
PostRepository::class => [
82
-
PostRepositoryPlugin::class,
83
-
],
84
-
],
85
-
];
79
+
```php
80
+
#[Before(sortOrder: 10)]
81
+
public function beforeGetPost(int $id): null { /* runs first */ }
86
82
```
87
83
88
84
## Plugin Execution Order
89
85
90
86
When multiple plugins target the same method:
91
87
92
-
1. All `before` plugins run (in module priority order)
93
-
2. The original method runs
94
-
3. All `after` plugins run (in module priority order)
88
+
1. All `before` plugins run (in sort order)
89
+
2. The original method runs (unless a before plugin short-circuited)
0 commit comments