Using array of middlewares for a route gives error

Following works:
$app->route(‘/login’, [App\Session\InitSessionMiddleware::class],[‘GET’, ‘POST’], ‘login’);
But the following gives error(“Illegal offset type in isset or empty”):
$app->route(‘/login’, [App\Session\InitSessionMiddleware::class, App\Login\LoginHandler::class],[‘GET’, ‘POST’], ‘login’);
Please let me know the right usage in this case.

Have you checked that the problem is not in your request handler LoginHandler? This error does not arise with a fresh installation and an array of middleware.

My Login Handler:

<?php

declare(strict_types=1);

namespace App\Login;

use Laminas\Diactoros\Response\HtmlResponse;
use Laminas\Diactoros\Response\RedirectResponse;
use Laminas\Diactoros\Uri;
use League\Plates\Engine;
use Mezzio\Session\SessionInterface;
use Mezzio\Template\TemplateRendererInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

use function in_array;

class LoginHandler implements RequestHandlerInterface
{
    private const REDIRECT_ATTRIBUTE = 'authentication:redirect';

    private $phpDataObjects;

    /** @var TemplateRendererInterface */
    private $renderer;

    public function __construct(TemplateRendererInterface $renderer, $phpDataObjects)
    {
        $this->renderer = $renderer;
        $this->phpDataObjects  = $phpDataObjects;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $method = $request->getMethod();
        $path   = $request->getUri()->getPath();

        if ($method === 'GET' && $path === '/login') {
            // Handle GET request for login form
            return $this->renderLoginForm();
        } elseif ($method === 'POST' && $path === '/login') {
            // Handle POST request for authentication
            return $this->handleLogin($request);
        } else {
            // Handle other requests (e.g., redirect to login page)
            return $this->redirectToLoginPage();
        }
    }

    private function renderLoginForm(): ResponseInterface
    {
        // Create a Plates template renderer
        $renderer = new Engine('/src/App/templates');

        // Render the login form template
        $loginFormHtml = $renderer->render('login'); // Assuming 'login-form' is the name of your login form template file

        // Create a PSR-7 response with the login form HTML
        return new HtmlResponse($loginFormHtml);
    }

    private function redirectToLoginPage(): ResponseInterface
    {
        // Assuming the login page URL is '/login'
        $loginPageUrl = '/login';

        // Create a redirect response to the login page
        return new RedirectResponse($loginPageUrl);
    }

    private function getRedirect(
        ServerRequestInterface $request,
        SessionInterface $session
    ): string {
        $redirect = $session->get(self::REDIRECT_ATTRIBUTE);

        if (! $redirect) {
            $redirect = new Uri($request->getHeaderLine('Referer'));
            if (in_array($redirect->getPath(), ['', '/login'], true)) {
                $redirect = '/';
            }
        }

        return (string) $redirect;
    }

}

Please check also your middleware InitSessionMiddleware.

My InitSessionMiddleware:

<?php

declare(strict_types=1);

namespace App\Session;

use Laminas\Diactoros\Response\HtmlResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class InitSessionMiddleware implements MiddlewareInterface
{
    protected $pdo;

    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // Initialize DatabasePersistentSessionInstance with PDO instance
        $sessionPersistence = new DatabasePersistentSessionInstance($this->pdo);

        // Initialize session from request
        $session = $sessionPersistence->initializeSessionFromRequest($request);

        // Perform some action (e.g., set session data)
        $session->set('user_id', 123);

        $session->set('username', 'john_doe');

        // Add a message or indicator to session data
        $session->set('_initialized', true);

        // Persist session in response
        $sessionPersistence->persistSession($session, $handler->handle($request));
        return new HtmlResponse('Hello ');
    }
}

Can you provide something more from the error message? File name or something else?
Otherwise we can only guess.

The return type of your InitSessionMiddleware middleware is wrong because you can not use a HTML response in front of another middleware.

public function process(
    ServerRequestInterface $request,
    RequestHandlerInterface $handler
): ResponseInterface {
    // Do something here…

    return $handler->handle($request);
}

See:

It don’t work even if I return:



return $sessionPersistence->persistSession($session, $handler->handle($request));;

The return type must be Psr\Http\Message\ResponseInterface and it doesn’t look like the method persistSession returns this type.
Unfortunately, I don’t know why you’re using $handler->handle($request) as parameter for the persistSession method.
Correct would be: return $handler->handle($request);

tried

return $handler->handle($request);

still same result.

Please recheck if and how the request handler App\Login\LoginHandler::class is registered. The service manager can not resolve this class.

LoginHandler registration is done in container.php:


$dependencies['factories'][LoginHandler::class] = function (ContainerInterface $container) {
    // Retrieve dependencies from the container
    $pdo = $container->get(PDO::class);

    // Instantiate and return LoginHandler with dependencies
    //return new LoginHandler($pdo);
    return new LoginHandler(
        $container->get(TemplateRendererInterface::class),
        $container->get($pdo)
    );
};

Can you create a repository for your project on GitHub to simplify the process of error analysis?
I am sure that the problem lies in your project and not in Mezzio.

Found it:

$pdo = $container->get(PDO::class);

// …

$container->get($pdo) // This caused the error!

That makes no sense!

Use this:

return new LoginHandler(
    $container->get(TemplateRendererInterface::class),
    $container->get(PDO::class)
);

This will most likely resolve both of your issues. If @froschdesign has resolved them both. Please mark them both as resolved as to help others searching similar problems :slight_smile:

Edit to add:

When fetching a identifier from the container. The psr requires a string identifier. Its best, as @froschdesign example shows, to use the ::class syntax for the target service. I would also suggest that when possible alias it to the interface. This allows swapping of underlying implementers without further changes.

Included the following in

<VirtualHost *:8888>
    ServerAdmin mezzio
    DocumentRoot "/Users/sanjivsharma/multibyte/newmezzio/public"
    ServerName mezzio.loc
ServerAlias mezzio.loc
    ErrorLog "logs/mezzioerror_log"
    CustomLog "logs/mezzioaccess_log" common
<Directory "/Users/sanjivsharma/multibyte/newmezzio/public">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

I missded adding the following earlier:

<Directory "/Users/sanjivsharma/multibyte/newmezzio/public">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
    </Directory>