Sie injizieren keine Middleware in andere Middleware. Sie injizieren Abhängigkeiten wie Services oder Repositories. Jede Middleware kümmert sich um eine bestimmte Aufgabe wie Authentifizierung, Autorisierung, Lokalisierungsverhandlung usw. Sie werden nacheinander ausgeführt. Sie machen sich mit der Anfrage herum und leiten die Anfrage an die nächste Middleware weiter. Sobald der Middleware-Stack aufgebraucht ist, wird die Antwort in umgekehrter Reihenfolge durch die gesamte Middleware zurückgegeben, bis sie schließlich die äußere Ebene erreicht, die die Ausgabe anzeigt. Eine Flussübersicht finden Sie in der expressive docs.
Ich würde nicht empfehlen, den Container und sicherlich nicht die App selbst zu injizieren. Obwohl es während der Entwicklung einfach sein könnte, wird Ihre Anwendung nicht testbar. Wenn Sie nur die benötigten Dienste in eine Middleware, eine Aktion oder einen Dienst injizieren, können Sie diese während der Tests leicht verspotten. Nach einer Weile gewöhnt man sich daran, Fabriken zu schreiben, wo es gebraucht wird, und es geht ziemlich schnell.
Das gleiche gilt für die Injektion des Entity Managers (wenn Sie Doktrin verwenden). Es ist einfacher, eine Anwendung zu testen, wenn Sie nur die benötigten Repositorys einspeisen, die Sie leicht nachahmen können.
Mit diesen Worten, wenn Sie nach einer einfachen Möglichkeit suchen, Abhängigkeiten zu injizieren, kann zend-servicemanager das tun. Werfen Sie einen Blick auf abstract factories. Mit einer abstrakten Fabrik können Sie eine Fabrik für alle Action-Klassen erstellen:
<?php
namespace App\Action;
use Interop\Container\ContainerInterface;
use ReflectionClass;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
class AbstractActionFactory implements AbstractFactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// Construct a new ReflectionClass object for the requested action
$reflection = new ReflectionClass($requestedName);
// Get the constructor
$constructor = $reflection->getConstructor();
if (is_null($constructor)) {
// There is no constructor, just return a new class
return new $requestedName;
}
// Get the parameters
$parameters = $constructor->getParameters();
$dependencies = [];
foreach ($parameters as $parameter) {
// Get the parameter class
$class = $parameter->getClass();
// Get the class from the container
$dependencies[] = $container->get($class->getName());
}
// Return the requested class and inject its dependencies
return $reflection->newInstanceArgs($dependencies);
}
public function canCreate(ContainerInterface $container, $requestedName)
{
// Only accept Action classes
if (substr($requestedName, -6) == 'Action') {
return true;
}
return false;
}
}
Ich schrieb einen blog post darüber.
Am Ende des Tages ist es Ihre eigene Entscheidung, aber die beste Praxis ist nicht die App, den Container oder den Entity Manager. Es wird Ihnen das Leben erleichtern, wenn Sie Ihre Middleware debuggen und/oder Tests dafür schreiben müssen.
Wäre es nicht besser, die Middleware Action durch 'MiddlewareInterface' zu implementieren und' 'canCreate' nach' return in_array ('MiddlewareInterface', class_implements ($ requestedName), true) '' Thanks btw! – cottton
Das ist ja auch möglich. Soweit ich weiß, ist es jedoch sehr teuer, Reflection zu verwenden. Ich möchte nicht alle meine Middleware automatisch initialisieren, nur eine Aktionsklasse pro Anfrage genügt mir. – xtreamwayz