Reputation: 868
I'm trying to use zend expressive nested application, so I'm following this blog post : https://framework.zend.com/blog/2017-03-15-nested-middleware-in-expressive.html
The problem seems to be in the Middleware factory:
class CreateBookMiddlewareFactory
{
public function __invoke(ContainerInterface $container)
{
$nested = new Application(
$container->get(RouterInterface::class),
$container
);
$nested->pipe(AuthenticationMiddleware::class);
$nested->pipe(ContentValidationMiddleware::class);
$nested->pipe(BodyParamsMiddleware::class);
$nested->pipe(BookValidationMiddleware::class);
$nested->pipe(CreateBookMiddleware::class);
return $nested;
}
}
I don't get how CreateBookMiddleware
could be added to the pipe here as we are in its Factory. So piping it will call the factory, create a new nested application, which will call the factory, which will create another nested application...
( ! ) Fatal error: Maximum function nesting level of '256' reached, aborting! in /var/www/project/vendor/zendframework/zend-stratigility/src/Next.php on line
158
Is there something I'm not getting right from this blog post?
Upvotes: 0
Views: 312
Reputation:
You named the factory CreateBookMiddlewareFactory
. And then inside __invoke
you have $nested->pipe(CreateBookMiddleware::class);
. It depends on your config, but usually CreateBookMiddlewareFactory would be the factory for CreateBookMiddleware. So it's stuck in a loop because it keeps creating itself.
As you have the exact same code as in the blogpost, I'm guessing it's an error in that blog post. I think it should have been like in the last delegator factory example: without the last $nested->pipe(CreateBookMiddleware::class);
.
I've notified the author of the blog post.
Edit: The blog post is updated with this fix:
namespace Acme\Api;
use Acme\AuthenticationMiddleware;
use Acme\ContentNegotiationMiddleware;
use Psr\Container\ContainerInterface;
use Zend\Expressive\Application;
use Zend\Expressive\Helper\BodyParams\BodyParamsMiddleware;
use Zend\Expressive\Router\RouterInterface;
class CreateBookMiddlewareFactory
{
public function __invoke(ContainerInterface $container)
{
$nested = new Application(
$container->get(RouterInterface::class),
$container
);
$nested->pipe(AuthenticationMiddleware::class);
$nested->pipe(ContentValidationMiddleware::class);
$nested->pipe(BodyParamsMiddleware::class);
$nested->pipe(BookValidationMiddleware::class);
// If dependencies are needed, pull them from the container and pass
// them to the constructor:
$nested->pipe(new CreateBookMiddleware());
return $nested;
}
}
Upvotes: 2
Reputation: 868
I accepted @xtreamwayz answer for the clarification. But here's how I made it work:
class CreateBookMiddlewareFactory
{
public function __invoke(ContainerInterface $container)
{
$nested = new Application(
$container->get(RouterInterface::class),
$container
);
$nested->pipe($container->get(AuthenticationMiddleware::class));
$nested->pipe($container->get(ContentValidationMiddleware::class));
$nested->pipe($container->get(BodyParamsMiddleware::class));
$nested->pipe($container->get(BookValidationMiddleware::class));
// instanciate the new class, so it will not call the factory again
$nested->pipe(new CreateBookMiddleware());
return $nested;
}
}
Upvotes: 0