Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 69 additions & 53 deletions docs/book/v2/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,25 @@ For example, to register an `AlbumListHandler` located in the `module/Applicatio
your `Application` module, add the following route to `module/Application/config/module.config.php`:

```php
use Application\Handler\AlbumListHandler;
use Application\Handler\BlogListHandler;
use Laminas\Mvc\Middleware\PipeSpec;
use Laminas\Router\Http\Literal;

return [
'service_manager' => [
'factories' => [
Middleware\BlogListMiddleware::class => Factory\BlogListMiddlewareFactory::class,
],
],
Comment on lines +18 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the important part of this pull request, because it fixed the problem. However, it should be added as a separate code example with its own headline.

Everything else should be dealt with in another proposal.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can recreate the PR in separate parts, if it helps, @voltan / @froschdesign.

'router' => [
'routes' => [
'album-list' => [
'blog-list' => [
'type' => Literal::class,
'options' => [
'route' => '/albums',
'route' => '/blog',
'defaults' => [
'controller' => PipeSpec::class,
'middleware' => AlbumListHandler::class,
'middleware' => Middleware\BlogListMiddleware::class,
],
],
],
Expand Down Expand Up @@ -66,99 +71,110 @@ A _RequestHandler_ is a class that receives a request and returns a response, wi
For more in-depth documentation visit the documentation for [Mezzio](https://docs.mezzio.dev/mezzio/v3/getting-started/features/)
and [Stratigility](https://docs.laminas.dev/laminas-stratigility/v3/intro/) or the [PSR-15 specification](https://www.php-fig.org/psr/psr-15/).

### Request Handlers
### Middleware

```php
namespace Application\Handler;
namespace Blog\Middleware;

use Application\Entity\Album;
use Blog\Repository\BlogListRepositoryInterface;
use Blog\Handler\BlogListnHandler;
use Fig\Http\Message\StatusCodeInterface;
use Laminas\Diactoros\StreamFactory;
use Laminas\Router\RouteMatch;
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;

class AlbumDetailMiddleware implements RequestHandlerInterface
class BlogListMiddleware implements MiddlewareInterface
{
/** @var BlogListRepositoryInterface */
public $blogListRepository;

/** @var ResponseFactoryInterface */
private $responseFactory;
public $responseFactory;

/** @var BlogListnHandler */
protected $handler;

/** @var StreamFactoryInterface */
private $streamFactory;
public $streamFactory;

public function __construct(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory)
public function __construct(BlogListRepositoryInterface $blogListRepository, ResponseFactoryInterface $responseFactory)
{
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
$this->blogListRepository = $blogListRepository;
$this->responseFactory = $responseFactory;
$this->streamFactory = new StreamFactory();
$this->handler = new BlogListnHandler($this->responseFactory, $this->streamFactory);
}

public function handle(ServerRequestInterface $request): ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
/** @var Album $album */
$album = $request->getAttribute('album');
/** @var RouteMatch $routeMatch */
$routeMatch = $request->getAttribute(RouteMatch::class);
$blogId = $routeMatch->getParam('blog_id');
$blogPost = $this->blogListRepository->findById($blogId);

$body = $this->streamFactory->createStream('The name of the album is: ' . $album->getName());
return $this->responseFactory->createResponse()->withBody($body);
// if no album was found, we short-circuit the pipe and return a 404 error:
if ($blogPost === null) {
return $this->responseFactory->createResponse(
StatusCodeInterface::STATUS_NOT_FOUND,
sprintf('Blog post with ID %s not found!', $blogId)
);
}

// ...otherwise we populate the request with the album and call the RequestHandler
$request = $request->withAttribute('blogPost', $blogPost);
return $this->handler->handle($request);
}
}
```

RequestHandlers resemble a single MVC Controller action, and will be used as the primary application functionality when
dispatching a request.
Middleware can return a direct response, in effect short-circuiting the middleware pipe, or pass request further
while having a chance to act on passed request or returned response.
Middleware in laminas-mvc is similar to [routed middleware](https://docs.mezzio.dev/mezzio/v3/features/router/piping/#routing)
in Mezzio.
> laminas-mvc does not have a global middleware pipe, so middleware can not be piped in front of MVC controllers.

### Middleware
### Request Handlers

```php
namespace Application\Middleware;
namespace Blog\Handler;

use Application\Repository\AlbumRepositoryInterface;
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\Message\StreamFactoryInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AlbumFromRouteMiddleware implements MiddlewareInterface
class BlogListHandler implements RequestHandlerInterface
{
/** @var AlbumRepositoryInterface */
private $albumRepository;
/** @var ResponseFactoryInterface */
private $responseFactory;
public $responseFactory;

public function __construct(AlbumRepositoryInterface $albumRepository, ResponseFactoryInterface $responseFactory)
/** @var StreamFactoryInterface */
public $streamFactory;

public function __construct(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory)
{
$this->albumRepository = $albumRepository;
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** @var RouteMatch $routeMatch */
$routeMatch = $request->getAttribute(RouteMatch::class);
$albumId = $routeMatch->getParam('album_id');
$album = $this->albumRepository->findById($albumId);
$blogPost = $request->getAttribute('blogPost');

// if no album was found, we short-circuit the pipe and return a 404 error:
if ($album === null) {
return $this->responseFactory->createResponse(
StatusCodeInterface::STATUS_NOT_FOUND,
sprintf('Album with ID %s not found!', $albumId)
);
}

// ...otherwise we populate the request with the album and call the RequestHandler
$request = $request->withAttribute('album', $album);
return $handler->handle($request);
$body = $this->streamFactory->createStream('The name of the blog post title is: ' . $blogPost->getTitle());
return $this->responseFactory->createResponse()->withBody($body);
}
}
```

Middleware can return a direct response, in effect short-circuiting the middleware pipe, or pass request further
while having a chance to act on passed request or returned response.
Middleware in laminas-mvc is similar to [routed middleware](https://docs.mezzio.dev/mezzio/v3/features/router/piping/#routing)
in Mezzio.
> laminas-mvc does not have a global middleware pipe, so middleware can not be piped in front of MVC controllers.
RequestHandlers resemble a single MVC Controller action, and will be used as the primary application functionality when
dispatching a request.

## Middleware Return Values

Expand Down