Controller plugins
A controller plugin is a small class with code needed in many actions. The familiar params(), redirect(), layout() and flashMessenger() are exactly such plugins. A plugin of your own saves you from copying the same lines from controller to controller.
Built-in plugins
| Call in an action | What it does |
|---|---|
$this->params() | Reads request parameters |
$this->redirect() | Redirects |
$this->url()->fromRoute('blog') | Builds an address from a route name |
$this->layout() | Controls the layout |
$this->forward()->dispatch(...) | Calls an action of another controller |
Your own plugin
The page number from the address is needed in every list, and each time it must be turned into a number not less than one. Let us move that into a plugin. Create the folder module/Blog/src/Controller/Plugin and a file in it:
// module/Blog/src/Controller/Plugin/PageNumber.php
namespace Blog\Controller\Plugin;
use Laminas\Mvc\Controller\Plugin\AbstractPlugin;
class PageNumber extends AbstractPlugin
{
public function __invoke(): int
{
$page = (int) $this->getController()->params()->fromQuery('page', 1);
return max(1, $page);
}
}The class extends AbstractPlugin. The __invoke() method runs when the plugin is called, and getController() returns the controller it was called from.
Registration
Plugins are described in the controller_plugins section of module/Blog/config/module.config.php:
// module/Blog/config/module.config.php
'controller_plugins' => [
'factories' => [
Controller\Plugin\PageNumber::class => InvokableFactory::class,
],
'aliases' => [
'pageNumber' => Controller\Plugin\PageNumber::class,
],
],factories says how to create the class, and aliases sets the short name under which the plugin is called in actions.
Calling it in an action
// module/Blog/src/Controller/PostController.php
public function indexAction()
{
$page = $this->pageNumber();
return new ViewModel(['page' => $page]);
}For /blog?page=3 the $page variable holds 3; for /blog?page=-5 and /blog?page=abc it holds 1. The plugin is available in every controller of the application, not only in the Blog module.
A plugin with dependencies
A plugin can receive services through its constructor. For example, this plugin returns the logged-in user:
// module/Blog/src/Controller/Plugin/CurrentUser.php
namespace Blog\Controller\Plugin;
use Laminas\Authentication\AuthenticationService;
use Laminas\Mvc\Controller\Plugin\AbstractPlugin;
class CurrentUser extends AbstractPlugin
{
public function __construct(private AuthenticationService $auth) {}
public function __invoke(): ?array
{
return $this->auth->hasIdentity() ? $this->auth->getIdentity() : null;
}
}In the configuration use ReflectionBasedAbstractFactory::class instead of InvokableFactory and add the alias currentUser. In an action $this->currentUser() returns an array with id and email, or null for a guest.
Common mistake
If you register a plugin in factories but forget the line in aliases, calling $this->pageNumber() ends with an exception saying a plugin with that name was not found. The short name is not derived from the class name — it is always set by an alias.