Skip to content

Commit d05ae68

Browse files
authored
Merge pull request #42 from dotkernel/issue-41
Issue #41: Added support for `laminas/laminas-servicemanager:4.x`
2 parents 6333a1f + e1a0b56 commit d05ae68

File tree

14 files changed

+412
-30
lines changed

14 files changed

+412
-30
lines changed

.laminas-ci.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"ignore_php_platform_requirements": {
3+
"8.4": true
4+
},
5+
"backwardCompatibilityCheck": true
6+
}

README.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
# dot-controller
22

3-
This is DotKernel's controller package that can be use like middleware inside DotKernel or Mezzio application.
3+
This is Dotkernel's controller package that can be use like middleware inside Dotkernel or Mezzio application.
44
It provides base classes for action based controllers similar to Laminas controller component. It is more lightweight though, but supports controller plugins and event listeners
55

66
![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-controller)
7-
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-controller/3.4.3)
7+
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-controller/4.0.0)
88

99
[![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/issues)
1010
[![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/network)
1111
[![GitHub stars](https://img.shields.io/github/stars/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/stargazers)
12-
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/blob/3.0/LICENSE.md)
12+
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-controller)](https://github.com/dotkernel/dot-controller/blob/4.0/LICENSE.md)
1313

1414
[![Build Static](https://github.com/dotkernel/dot-controller/actions/workflows/static-analysis.yml/badge.svg?branch=3.0)](https://github.com/dotkernel/dot-controller/actions/workflows/static-analysis.yml)
1515
[![codecov](https://codecov.io/gh/dotkernel/dot-controller/graph/badge.svg?token=VUBG5LM4CK)](https://codecov.io/gh/dotkernel/dot-controller)
1616

17-
[![SymfonyInsight](https://insight.symfony.com/projects/c4aac671-40d7-4590-b1fa-b3e46a1e3f43/big.svg)](https://insight.symfony.com/projects/c4aac671-40d7-4590-b1fa-b3e46a1e3f43)
18-
1917
## Installation
2018

2119
Install `dot-controller` by executing the following Composer command:
2220

23-
```bash
24-
$ composer require dotkernel/dot-controller
21+
```shell
22+
composer require dotkernel/dot-controller
2523
```
2624

2725
## Usage
@@ -32,14 +30,14 @@ Middleware controllers act as a handler for multiple routes. Some conventions we
3230
- action parameter value is converted to a method name inside the controller. Underscore, dot and line characters are removed and the action name is converted to camel-case suffixed by the string `Action`. For example a route and action pair like `/user/forgot-password` will be converted to method `forgotPasswordAction`.
3331
- the default action value, if not present in the URI is `index`, so you should always define an `indexAction` within your controllers for displaying a default page or redirecting.
3432

35-
In order to create your action based controllers, you must extend the abstract class `DotKernel\DotController\AbstractActionController`
33+
In order to create your action based controllers, you must extend the abstract class `Dot\Controller\AbstractActionController`.
3634

3735
### Example
3836

39-
Creating a UserController with default action and a register action. Will handle routes `/user` and `/user/register`
37+
Creating a UserController with default action and a register action. Will handle routes `/user` and `/user/register`.
4038

4139
```php
42-
use DotKernel\DotController\AbstractActionController;
40+
use Dot\Controller\AbstractActionController;
4341

4442
class UserController extends AbstractActionController
4543
{
@@ -58,7 +56,7 @@ class UserController extends AbstractActionController
5856
Then register this controller as a routed middleware in file `RoutesDelegator.php` just like a regular middleware.
5957

6058
```php
61-
//Example from a DotKernel RoutesDelegator
59+
//Example from a RoutesDelegator
6260
$app->route(
6361
'/user[/{action}]',
6462
UserController::class,
@@ -74,5 +72,5 @@ Use case: You have defined a controller inside some package, with default action
7472
- create your own controller, independent of the package's controller which adds more actions
7573
- Mezzio lets you define an array of middleware for a route, so you can register this controller before the package's controller
7674

77-
Now when a request for this route comes in, your controller will run first. DotKernel controllers are designed to ignore requests that cannot be matched to one of its methods, so if no action matches, it will call the next middleware, in our case, the second controller.
75+
Now when a request for this route comes in, your controller will run first. Dotkernel controllers are designed to ignore requests that cannot be matched to one of its methods, so if no action matches, it will call the next middleware, in our case, the second controller.
7876
If this is the last controller, and action does not match here, it will go to the default 404 Not found page(handled by NotFoundDelegate)

composer.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818
}
1919
],
2020
"require": {
21-
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
22-
"psr/http-message": "^1.0 || ^2.0",
23-
"laminas/laminas-servicemanager": "^3.11.2",
24-
"dotkernel/dot-event": "^3.2.0",
21+
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
22+
"dotkernel/dot-event": "^4.0.0",
23+
"laminas/laminas-servicemanager": "^4.0",
24+
"mezzio/mezzio-helpers": "^5.8.0",
2525
"mezzio/mezzio-template": "^2.4.0",
26-
"mezzio/mezzio-helpers": "^5.8.0"
26+
"psr/http-message": "^1.0 || ^2.0"
2727
},
2828
"require-dev": {
29+
"laminas/laminas-coding-standard": "^3.0",
30+
"laminas/laminas-diactoros": "^3.0",
2931
"phpunit/phpunit": "^10.2",
30-
"vimeo/psalm": "^5.13",
31-
"laminas/laminas-coding-standard": "^2.5",
32-
"laminas/laminas-diactoros": "^3.0"
32+
"vimeo/psalm": "^5.13"
3333
},
3434
"autoload": {
3535
"psr-4": {
@@ -44,7 +44,8 @@
4444
"scripts": {
4545
"check": [
4646
"@cs-check",
47-
"@test"
47+
"@test",
48+
"@static-analysis"
4849
],
4950
"cs-check": "phpcs",
5051
"cs-fix": "phpcbf",

docs/book/index.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/book/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../README.md

docs/book/v4/configuration.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Configuration
2+
3+
After installation, the package can be used immediately but if you want to use all features of the package, like plugins and events you need to register the `ConfigProvider` in your project by adding the below line to your configuration aggregator (usually: `config/config.php`):
4+
5+
\Dot\Controller\ConfigProvider::class

docs/book/v4/events.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Events
2+
3+
DotKernel's controller package supports events and those events can be of 2 types: global events (middleware-like) or manually dispatch events.
4+
5+
## Getting started
6+
7+
- Every event listener that is triggered from a controller
8+
needs to implement `Dot\Controller\Event\ControllerEventListenerInterface` which actually extends `Laminas\EventManager\ListenerAggregateInterface`.
9+
- You can add the trait `Dot\Controller\Event\ControllerEventListenerTrait` to override the method of the interface.
10+
- Every event listener needs to be registered under the `['dot_controller']['event_listenenrs]` key in the ConfigProvider, and every key must be the class that you want to attach the events
11+
12+
## Usage
13+
14+
The events in a controller can be done in 2 different ways, a global way where an event is attached automatically to all the controllers action and works in the same way the middlewares works
15+
or a manually dispatchable way, where you can define to which controller the events is attached, and you can trigger the event where you want.
16+
17+
For our example we have a UserController with some methods in it
18+
19+
```php
20+
use DotKernel\DotController\AbstractActionController;
21+
22+
class UserController extends AbstractActionController
23+
{
24+
public function indexAction()
25+
{
26+
//...
27+
}
28+
29+
public function registerAction()
30+
{
31+
//...
32+
}
33+
34+
// post method for updating the user
35+
public function updateAction()
36+
{
37+
38+
}
39+
}
40+
```
41+
42+
### Example 1 - Global way
43+
44+
First we will create the event listener
45+
46+
```php
47+
use Dot\Controller\Event\ControllerEvent;
48+
use Dot\Controller\Event\ControllerEventListenerInterface;
49+
use Dot\Controller\Event\ControllerEventListenerTrait;
50+
51+
// for the logger we assume you will use your own logger and inject it
52+
53+
class UserUpdatedListener implements ControllerEventListenerInterface
54+
{
55+
use ControllerEventListenerTrait;
56+
57+
public function onBeforeDispatch(ControllerEvent $event): void
58+
{
59+
$this->logger->info('on before dispatch');
60+
}
61+
62+
public function onAfterDispatch(ControllerEvent $event): void
63+
{
64+
$this->logger->info('on after dispatch');
65+
}
66+
67+
}
68+
```
69+
70+
We register the event listener in the configuration key
71+
72+
```php
73+
'dot_controller' => [
74+
'event_listeners' => [
75+
AccountController::class => [
76+
UserUpdatedListener::class,
77+
]
78+
]
79+
]
80+
```
81+
82+
As you can assume, `onBeforeDispatch` is triggered right before the controller is dispatched, and `onAfterDispatch` right
83+
after the controller is dispatched.
84+
85+
With this it doesn't matter what action is accessed, the event it will run before and after the action.
86+
87+
In addition, you can make use of the `event` variable to access information about the event.
88+
89+
For example:
90+
91+
```php
92+
// UserUpdatedListener
93+
public function onAfterDispatch(ControllerEvent $e): void
94+
{
95+
$method = $e->getTarget()->getRequest()->getMethod();
96+
$action = $e->getParams()['method'];
97+
if ($method == 'POST' && $action == 'updateAction') {
98+
$this->logger->info('this will trigger ');
99+
100+
}
101+
}
102+
```
103+
104+
So every time the `updateAction` is accessed and the method is post,
105+
right after the action is dispatched, we can log that the user was updated.
106+
107+
We can use the `onBeforeDispatch` in the same way, to log right before the user is updated.
108+
109+
### Example 2 - Manually triggered way
110+
111+
```php
112+
use Dot\Controller\Event\ControllerEvent;
113+
use Dot\Controller\Event\ControllerEventListenerInterface;
114+
use Dot\Controller\Event\ControllerEventListenerTrait;
115+
116+
// for the logger we assume you will use your own logger and inject it
117+
118+
class UserUpdatedListener implements ControllerEventListenerInterface
119+
{
120+
use ControllerEventListenerTrait;
121+
122+
public function attach(EventManagerInterface $events, $priority = 1): void
123+
{
124+
$this->listeners[] = $events->attach(
125+
'user.profile.update',
126+
[$this, 'userProfileUpdated'],
127+
$priority
128+
);
129+
}
130+
131+
public function userProfileUpdated(ControllerEvent $event): void
132+
{
133+
$this->logger->info('User profile updated');
134+
}
135+
136+
}
137+
```
138+
139+
The `attach` method is from the `ListenerAggregateInterface` which `ControllerEventListenerTrait`
140+
already is overriding it so can be used in a global way with `onBeforeDispatch` and `onAfterDispatch`
141+
methods, but we can make our custom event and bind it to our method.
142+
143+
In this case we create attach an event called `user.profile.update` and bind it to the `userProfileUpdated` method.
144+
145+
Next we need to register the event
146+
147+
```php
148+
'dot_controller' => [
149+
'event_listeners' => [
150+
AccountController::class => [
151+
'user.profile.update' => UserUpdatedListener::class
152+
]
153+
]
154+
]
155+
```
156+
157+
Now you can manually trigger the event from the controller using build in `dispatchEvent` method.
158+
159+
```php
160+
// UserController
161+
// post method for updating the user
162+
public function updateAction()
163+
{
164+
// logic
165+
$this->dispatchEvent('user.profile.update', ['user' => $user]);
166+
167+
}
168+
```
169+
170+
As you can see we attach the `user` key to the parameters, so we can actually access it.
171+
172+
```php
173+
public function userProfileUpdated(ControllerEvent $event): void
174+
{
175+
$user = $event->getParams()['user'];
176+
$this->logger->info('User profile updated', $user->toArray());
177+
}
178+
```

docs/book/v4/installation.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Installation
2+
3+
Install `dot-controller` by executing the following Composer command:
4+
5+
composer require dotkernel/dot-controller

docs/book/v4/overview.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Overview
2+
3+
`dot-controller` is DotKernel's controller package that can be use like middleware inside DotKernel or Mezzio application.
4+
It provides base classes for action based controllers similar to Laminas controller component. It is more lightweight though, but supports controller plugins and event listeners

0 commit comments

Comments
 (0)