<?php
namespace User\Middleware;
use Fig\Http\Message\StatusCodeInterface;
use Laminas\Router\RouteMatch;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use User\Repository\AccountRepositoryInterface;
class AuthenticationMiddleware implements MiddlewareInterface
{
/** @var AccountRepositoryInterface */
public $accountRepository;
/** @var ResponseFactoryInterface */
public $responseFactory;
public function __construct(AccountRepositoryInterface $accountRepository, ResponseFactoryInterface $responseFactory)
{
$this->accountRepository = $accountRepository;
$this->responseFactory = $responseFactory;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
/** @var RouteMatch $routeMatch */
$routeMatch = $request->getAttribute(RouteMatch::class);
$userId = $routeMatch->getParam('id');
$account = $this->accountRepository->getAccount(['id' => $userId]);
// if no album was found, we short-circuit the pipe and return a 404 error:
if ($account === null) {
return $this->responseFactory->createResponse(
StatusCodeInterface::STATUS_NOT_FOUND,
sprintf('Album with ID %s not found!', $userId)
);
}
// ...otherwise we populate the request with the album and call the RequestHandler
$request = $request->withAttribute('account', $account);
return $handler->handle($request);
}
}
and handler class
<?php
namespace User\Handler;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Server\RequestHandlerInterface;
class AuthenticationHandler implements RequestHandlerInterface
{
/** @var ResponseFactoryInterface */
public $responseFactory;
/** @var StreamFactoryInterface */
public $streamFactory;
public function __construct(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory)
{
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
// /** @var $album */
$account = $request->getAttribute('account');
$body = $this->streamFactory->createStream('The name of the user is: ' . $account->getName());
return $this->responseFactory->createResponse()->withBody($body);
}
}
Can you please check it and tell me what is the problem? or perhaps I miss someting
Hello again
I finally finish Middleware and check it, My use-case was to get a JWT token from UTL (as a query string) and check user
But if I understand true, in MVC I could not write global Middleware and run it before each request for the normal controller
If I want use Middleware, I should write Handler ( as a single action controller ). But can I use one Middleware for some of my Handler, for example, I want to create profile-view, profile-edit, logout, submit-post, and … actions ( All of them should be handlers) and get user token and check validation and after that run handler.
It’s true? and the best way for this use-case? or it better I write service for it and run it on controller or actions? or another way?
<?php
namespace User\Middleware;
use Fig\Http\Message\StatusCodeInterface;
use Laminas\Diactoros\StreamFactory;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use User\Handler\AuthenticationHandler;
use User\Repository\AccountRepositoryInterface;
use User\Service\AuthService;
class AuthenticationMiddleware implements MiddlewareInterface
{
/** @var AccountRepositoryInterface */
public $accountRepository;
/** @var ResponseFactoryInterface */
public $responseFactory;
/** @var AuthService */
protected $authService;
/** @var AuthenticationHandler */
protected $handler;
/** @var StreamFactoryInterface */
public $streamFactory;
public function __construct(AccountRepositoryInterface $accountRepository, ResponseFactoryInterface $responseFactory)
{
$this->accountRepository = $accountRepository;
$this->responseFactory = $responseFactory;
$this->streamFactory = new StreamFactory();
$this->authService = new AuthService();
$this->handler = new AuthenticationHandler($this->responseFactory, $this->streamFactory);
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$params = $request->getQueryParams();
if (!isset($params['token']) || empty($params['token'])) {
die('to token !');
}
$token = $this->authService->parseToken($params['token']);
if (empty($token)) {
die('to token !');
}
$account = $this->accountRepository->getAccount(['id' => $token->uid]);
if (empty($account)) {
die('no user !');
}
if ($account === null) {
return $this->responseFactory->createResponse(
StatusCodeInterface::STATUS_NOT_FOUND,
sprintf('Album with ID %s not found!', $token->uid)
);
}
$request = $request->withAttribute('account', $account);
return $this->handler->handle($request);
}
}
AuthenticationHandler ( or another handler for example logout or update profile )
<?php
namespace User\Handler;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Server\RequestHandlerInterface;
class AuthenticationHandler implements RequestHandlerInterface
{
/** @var ResponseFactoryInterface */
public $responseFactory;
/** @var StreamFactoryInterface */
public $streamFactory;
public function __construct(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory)
{
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$account = $request->getAttribute('account');
$body = $this->streamFactory->createStream('The name of the user is: ' . $account->getName());
return $this->responseFactory->createResponse()->withBody($body);
}
}
Questions:
I use Laminas\Diactoros\StreamFactory in middleware and as Psr StreamFactoryInterface in the handler, it true?