Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #41: Added support for laminas/laminas-servicemanager:4.x #42

Merged
merged 3 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .laminas-ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ignore_php_platform_requirements": {
"8.4": true
},
"backwardCompatibilityCheck": true
}
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
# dot-controller

This is DotKernel's controller package that can be use like middleware inside DotKernel or Mezzio application.
This is Dotkernel's controller package that can be use like middleware inside Dotkernel or Mezzio application.
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

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

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

[![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)
[![codecov](https://codecov.io/gh/dotkernel/dot-controller/graph/badge.svg?token=VUBG5LM4CK)](https://codecov.io/gh/dotkernel/dot-controller)

[![SymfonyInsight](https://insight.symfony.com/projects/c4aac671-40d7-4590-b1fa-b3e46a1e3f43/big.svg)](https://insight.symfony.com/projects/c4aac671-40d7-4590-b1fa-b3e46a1e3f43)

## Installation

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

```bash
$ composer require dotkernel/dot-controller
```shell
composer require dotkernel/dot-controller
```

## Usage
Expand All @@ -32,14 +30,14 @@ Middleware controllers act as a handler for multiple routes. Some conventions we
- 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`.
- 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.

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

### Example

Creating a UserController with default action and a register action. Will handle routes `/user` and `/user/register`
Creating a UserController with default action and a register action. Will handle routes `/user` and `/user/register`.

```php
use DotKernel\DotController\AbstractActionController;
use Dot\Controller\AbstractActionController;

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

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

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.
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.
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)
19 changes: 10 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@
}
],
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
"psr/http-message": "^1.0 || ^2.0",
"laminas/laminas-servicemanager": "^3.11.2",
"dotkernel/dot-event": "^3.2.0",
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
"dotkernel/dot-event": "^4.0.0",
"laminas/laminas-servicemanager": "^4.0",
"mezzio/mezzio-helpers": "^5.8.0",
"mezzio/mezzio-template": "^2.4.0",
"mezzio/mezzio-helpers": "^5.8.0"
"psr/http-message": "^1.0 || ^2.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "^3.0",
"laminas/laminas-diactoros": "^3.0",
"phpunit/phpunit": "^10.2",
"vimeo/psalm": "^5.13",
"laminas/laminas-coding-standard": "^2.5",
"laminas/laminas-diactoros": "^3.0"
"vimeo/psalm": "^5.13"
},
"autoload": {
"psr-4": {
Expand All @@ -44,7 +44,8 @@
"scripts": {
"check": [
"@cs-check",
"@test"
"@test",
"@static-analysis"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
Expand Down
1 change: 0 additions & 1 deletion docs/book/index.md

This file was deleted.

1 change: 1 addition & 0 deletions docs/book/index.md
5 changes: 5 additions & 0 deletions docs/book/v4/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Configuration

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`):

\Dot\Controller\ConfigProvider::class
178 changes: 178 additions & 0 deletions docs/book/v4/events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Events

DotKernel's controller package supports events and those events can be of 2 types: global events (middleware-like) or manually dispatch events.

## Getting started

- Every event listener that is triggered from a controller
needs to implement `Dot\Controller\Event\ControllerEventListenerInterface` which actually extends `Laminas\EventManager\ListenerAggregateInterface`.
- You can add the trait `Dot\Controller\Event\ControllerEventListenerTrait` to override the method of the interface.
- 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

## Usage

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
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.

For our example we have a UserController with some methods in it

```php
use DotKernel\DotController\AbstractActionController;

class UserController extends AbstractActionController
{
public function indexAction()
{
//...
}

public function registerAction()
{
//...
}

// post method for updating the user
public function updateAction()
{

}
}
```

### Example 1 - Global way

First we will create the event listener

```php
use Dot\Controller\Event\ControllerEvent;
use Dot\Controller\Event\ControllerEventListenerInterface;
use Dot\Controller\Event\ControllerEventListenerTrait;

// for the logger we assume you will use your own logger and inject it

class UserUpdatedListener implements ControllerEventListenerInterface
{
use ControllerEventListenerTrait;

public function onBeforeDispatch(ControllerEvent $event): void
{
$this->logger->info('on before dispatch');
}

public function onAfterDispatch(ControllerEvent $event): void
{
$this->logger->info('on after dispatch');
}

}
```

We register the event listener in the configuration key

```php
'dot_controller' => [
'event_listeners' => [
AccountController::class => [
UserUpdatedListener::class,
]
]
]
```

As you can assume, `onBeforeDispatch` is triggered right before the controller is dispatched, and `onAfterDispatch` right
after the controller is dispatched.

With this it doesn't matter what action is accessed, the event it will run before and after the action.

In addition, you can make use of the `event` variable to access information about the event.

For example:

```php
// UserUpdatedListener
public function onAfterDispatch(ControllerEvent $e): void
{
$method = $e->getTarget()->getRequest()->getMethod();
$action = $e->getParams()['method'];
if ($method == 'POST' && $action == 'updateAction') {
$this->logger->info('this will trigger ');

}
}
```

So every time the `updateAction` is accessed and the method is post,
right after the action is dispatched, we can log that the user was updated.

We can use the `onBeforeDispatch` in the same way, to log right before the user is updated.

### Example 2 - Manually triggered way

```php
use Dot\Controller\Event\ControllerEvent;
use Dot\Controller\Event\ControllerEventListenerInterface;
use Dot\Controller\Event\ControllerEventListenerTrait;

// for the logger we assume you will use your own logger and inject it

class UserUpdatedListener implements ControllerEventListenerInterface
{
use ControllerEventListenerTrait;

public function attach(EventManagerInterface $events, $priority = 1): void
{
$this->listeners[] = $events->attach(
'user.profile.update',
[$this, 'userProfileUpdated'],
$priority
);
}

public function userProfileUpdated(ControllerEvent $event): void
{
$this->logger->info('User profile updated');
}

}
```

The `attach` method is from the `ListenerAggregateInterface` which `ControllerEventListenerTrait`
already is overriding it so can be used in a global way with `onBeforeDispatch` and `onAfterDispatch`
methods, but we can make our custom event and bind it to our method.

In this case we create attach an event called `user.profile.update` and bind it to the `userProfileUpdated` method.

Next we need to register the event

```php
'dot_controller' => [
'event_listeners' => [
AccountController::class => [
'user.profile.update' => UserUpdatedListener::class
]
]
]
```

Now you can manually trigger the event from the controller using build in `dispatchEvent` method.

```php
// UserController
// post method for updating the user
public function updateAction()
{
// logic
$this->dispatchEvent('user.profile.update', ['user' => $user]);

}
```

As you can see we attach the `user` key to the parameters, so we can actually access it.

```php
public function userProfileUpdated(ControllerEvent $event): void
{
$user = $event->getParams()['user'];
$this->logger->info('User profile updated', $user->toArray());
}
```
5 changes: 5 additions & 0 deletions docs/book/v4/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Installation

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

composer require dotkernel/dot-controller
4 changes: 4 additions & 0 deletions docs/book/v4/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Overview

`dot-controller` is DotKernel's controller package that can be use like middleware inside DotKernel or Mezzio application.
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
Loading
Loading