GithubHelp home page GithubHelp logo

mezzio / mezzio Goto Github PK

View Code? Open in Web Editor NEW
325.0 34.0 53.0 12.04 MB

PSR-15 Middleware Microframework

Home Page: https://docs.mezzio.dev/mezzio/

License: BSD 3-Clause "New" or "Revised" License

PHP 100.00%
psr-15 middleware middleware-framework

mezzio's Introduction

mezzio

Build Status Type Coverage

Develop PSR-7 middleware applications in minutes!

mezzio builds on laminas-stratigility to provide a minimalist PSR-7 middleware framework for PHP, with the following features:

Installation

We provide two ways to install Mezzio, both using Composer: via our skeleton project and installer, or manually.

Using the skeleton + installer

The simplest way to install and get started is using the skeleton project, which includes installer scripts for choosing a router, dependency injection container, and optionally a template renderer and/or error handler. The skeleton also provides configuration for officially supported dependencies.

To use the skeleton, use Composer's create-project command:

composer create-project mezzio/mezzio-skeleton <project dir>

This will prompt you through choosing your dependencies, and then create and install the project in the <project dir> (omitting the <project dir> will create and install in a mezzio-skeleton/ directory).

Manual Composer installation

You can install Mezzio standalone using Composer:

composer require mezzio/mezzio

However, at this point, Mezzio is not usable, as you need to supply minimally:

  • a router.
  • a dependency injection container.

We currently support and provide the following routing integrations:

We recommend using a dependency injection container, and typehint against PSR-11 Container. We can recommend the following implementations:

  • laminas-servicemanager: composer require laminas/laminas-servicemanager
  • Pimple (see docs for more details): composer require laminas/laminas-pimple-config
  • Aura.Di (see docs for more details): composer require laminas/laminas-auradi-config

Additionally, you may optionally want to install a template renderer implementation, and/or an error handling integration. These are covered in the documentation.

Documentation

Documentation is in the doc tree, and can be compiled using mkdocs:

mkdocs build

Additionally, public-facing, browseable documentation is available at https://docs.mezzio.dev/mezzio/

mezzio's People

Contributors

acelaya avatar bakura10 avatar batumibiz avatar belgattitude avatar boesing avatar danizord avatar ezimuel avatar froschdesign avatar geerteltink avatar ghostwriter avatar gsteel avatar harikt avatar jensdenies avatar kynx avatar lcobucci avatar maks3w avatar michaelmoussa avatar michalbundyra avatar mtymek avatar mwillbanks avatar ocramius avatar ojhaujjwal avatar pine3ree avatar renovate[bot] avatar samsonasik avatar settermjd avatar snapshotpl avatar spiffyjr avatar weierophinney avatar xerkus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mezzio's Issues

[RFC]: Mezzio v4

RFC

Q A
Proposed Version(s) 4.0.0
BC Break? Yes

Goal

  • Remove callable response factory support
  • Add latest coding standard and add declare(strict_types=1); where its missing

Background

We already prepared v3 to support native PSR-17 factories (when available) and now we just have to create a new major to drop support for the callable factory.

Considerations

mezzio/mezzio (like laminas/laminas-mvc) is supposed to work as a "project". I dont think that there are too many components which depend on it and thus, we can safely create a new major.

Proposal(s)

To get fully PSR-17 compatible, we just have to remove the ResponseInterface service usage (which was used to receive a callable which creates a PSR-7 ResponseInterface when being invoked.

Appendix

Affected components

Component PSR-17 compatible
mezzio/mezzio-router ❗ as of 3.6.0 ResponseFactoryInterface, StreamFactoryInterface still missing
mezzio/mezzio-authentication-basic ✔️ as of 1.4.0
mezzio/mezzio-authentication-laminasauthentication ✔️ as of 1.3.0
mezzio/mezzio-authentication-oauth2 ✔️ as of 2.4.0
mezzio/mezzio-authentication-session ✔️ as of 1.4.0
mezzio/mezzio-authorization ✔️ as of 1.4.0
mezzio/mezzio-hal ✔️ as of 2.3.0
mezzio/mezzio-problem-details ✔️ as of 1.5.0
mezzio/mezzio-problem-details
laminas/laminas-httphandlerrunner not affected

Project to keep track of current implementation status

Support for PSR-17

RFC

Q A
Proposed Version(s) 3.3.0
BC Break? No

Goal

Mezzio has its own convention to create an instance of ResponseInterface and ServerRequestInterface.
One has to use laminas-diactoros which works out-of the box with mezzio due to several internal factories or one has to create those callables to ensure other PSR-7 packages are working.

I'd like to change this to PSR-17 factories instead which would enable packages to provide some kind of autowiring (like in laminas-diactoros).

Background

I am currently working on a Proxy request handler which should pass a provided ServerRequestInterface to another, external API with cURL. I see that diactoros has some kind of $_POST usage which passes multipart/form-data to parsedBody while the Body StreamInterface contains php://input which does not contain the multipart/form-data stuff.

This is kinda weird as I would expect containing the StreamInterface having the "RAW" data of that request while parsedBody is some kind of pre-parsed Body.

I want to verify if thats probably some diactoros-related bug by switching the underlying PSR-7 library but as I can't just provide the configuration as in laminas-diactoros (ConfigProvider, see link above) but have to write code for this, I realized that this is not the de-facto standard PSR-17 but an own implementation.

Considerations

When implementing PSR-17, this would mean that we can either support the callables or the PSR-17 factory interfaces.
We can either change this in a major version or add this within a minor version and provide callables from the current existing factories (in case they're available) and remove the callable logic with the next major.

In case we want to introduce a BC-Break in the next major, we need to document this breaking change but forward compatibility would be quite easy to apply as laminas-diactoros already provide the ConfigProvider example on how that might look like.

If an application uses an other PSR-7 implementation, they have just to provide the mapping from the interface to the implementation (which can be like copy & paste from the laminas-diactoros package).

Proposal(s)

Current "factories" could consume PSR-17 factories and wrapping these in the callables.

Those "services" which are working with those callables don't need changes until we bump the major of this package and thus changing the __construct to consume PSR-17 interfaces instead of callables.

So we can provide some kind of forward-compatibility regarding the configuration but there has to be a hard BC break with the next major version bump to switch from callable annotation to *Interface annotation.

Appendix

Currently known packages which are affected by this change:

Maybe there are more packages, I did not check any package around tho.

[RFC]: Provide an ApplicationProgrammaticConfigDelegator that pairs with ApplicationConfigInjectionDelegator

RFC

Q A
Proposed Version(s) 3.x
BC Break? No

Goal

Standardize how routes and middleware are piped into the application, by providing a, let's call it ApplicationProgrammaticConfigDelegator, that wraps the logic of loading the config/routes.php and config/pipeline.php files.

Then, users would need to decorate their Application service with either ApplicationProgrammaticConfigDelegator or ApplicationConfigInjectionDelegator (or none, if they want to follow a completely different approach).

The skeleton application would use this new delegator by default.

Background

I find myself in the next situation:

I have a mezzio-based project where I have been historically defining routes and middlewares via configuration, so I had my Application service decorated with ApplicationConfigInjectionDelegator.

When the mezzio-swoole package was created (still zend-expressive-swoole back then), I started experimenting with it, in order to support serving this application with swoole.

On its first versions, the command to start a mezzio app with swoole was more opinionated, and always tried to load the config/routes.php and config/pipeline.php files, which did not exist in my case, making the start-up fail.

I provided a PR to make the loading optional, and I have been successfully using it since.

Recently I have also added support for RoadRunner, so now the project can be bootstrapped/run in three different ways (plus the CLI).

Also recently, due to a couple of new features, the loading of routes and middleware via config has become more inconvenient, and using the programmatic approach mkes more sense now.

The problem is that I now have two different scopes (php-fp and roadrunner) where I have to manually require the routes.php and pipeline.php files, as they have different entry points.

I have considered writting a common script which is then used by both entry points, but I already have too many scripts "calling" each other and it's becoming harder to follow.

I have also considered writting this delegator myself, but this would conflict with mezzio-swoole's start command, since it would try to load them again. I would need to conditionally register this delegator based on the execution context.

Considerations

On mezzio, none that I can think of. Users would need to add the new delegator and remove the manually requirement of the files from their entry points, but as long as they don't do it, everything should continue working.

On mezzio-swoole, the logic that right now loads those files if they exist, would need to somehow check if they have been already included, and avoid it in that case. That would keep backwards compatibility. Including this in a major version and just removing the logic from the start command would be another option.

Proposal(s)

As already more or less explained, my proposal would be to be less opinionated on mezzio-swoole, and also avoid forcing entry points to require the two mentioned files, in case the project has multiple entry points.

Instead, mezzio would provide two ways to load the config, which would require decorating the Application service one way or another (the docs should explain both options).

Then, different entry points would be able to pull the Application service from the container and it would already have all the config no matter the entry point.

NotFoundHandler generateTemplatedResponse Content Type missing

I believe "Content-Type" header is missing from the newly created response object when a 404 error is handled.

/src/Handler/NotFoundHandler.php

/**
     * Generates a response using a template.
     *
     * Template will receive the current request via the "request" variable.
     */
    private function generateTemplatedResponse(
        TemplateRendererInterface $renderer,
        ServerRequestInterface $request
    ) : ResponseInterface {

        $response = ($this->responseFactory)()->withStatus(StatusCodeInterface::STATUS_NOT_FOUND);
        $response->getBody()->write(
            $renderer->render($this->template, ['request' => $request, 'layout' => $this->layout])
        );

        return $response;
    }

Should be

/**
     * Generates a response using a template.
     *
     * Template will receive the current request via the "request" variable.
     */
    private function generateTemplatedResponse(
        TemplateRendererInterface $renderer,
        ServerRequestInterface $request
    ) : ResponseInterface {

        $response = ($this->responseFactory)()
                 ->withHeader('Content-Type', 'text/html')
                 ->withStatus(StatusCodeInterface::STATUS_NOT_FOUND);
        $response->getBody()->write(
            $renderer->render($this->template, ['request' => $request, 'layout' => $this->layout])
        );

        return $response;
    }

Originally posted by @cgaube at zendframework/zend-expressive#647

Several selectable DI Containers do not implement Interop\Container, causing an error in Zend Expressive 3

I set up a fresh installation of Zend Expressive 3 through the composer create-project command, and selected the following options:

  • Modular installation type
  • Symfony DI Container
  • FastRoute router
  • Zend-view template engine
  • Whoops error handler

Without adjusting anything within the project and accessing the project in my local development environment I'm faced with the following error:

Fatal error: Uncaught Zend\ServiceManager\Exception\InvalidArgumentException: Zend\ServiceManager\AbstractPluginManager expects a ConfigInterface or ContainerInterface instance as the first argument; received Symfony\Component\DependencyInjection\ContainerBuilder in /var/www/zend-expressive-skeleton/vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php:59 Stack trace: #0 /var/www/zend-expressive-skeleton/vendor/zendframework/zend-view/src/HelperPluginManager.php(253): Zend\ServiceManager\AbstractPluginManager->__construct(Object(Symfony\Component\DependencyInjection\ContainerBuilder), Array) #1 /var/www/zend-expressive-skeleton/vendor/zendframework/zend-expressive-zendviewrenderer/src/HelperPluginManagerFactory.php(20): Zend\View\HelperPluginManager->__construct(Object(Symfony\Component\DependencyInjection\ContainerBuilder)) #2 /var/www/zend-expressive-skeleton/vendor/jsoumelidis/zend-sf-di-config/src/CallbackFactory.php(94): Zend\Expressive\ZendView\HelperPluginManagerFactory->__invoke(Object(Symfony\Com in /var/www/zend-expressive-skeleton/vendor/zendframework/zend-servicemanager/src/AbstractPluginManager.php on line 59

The problem seems to be that the application can not be instantiated as AbstractPluginManager (by extension by the HelperPluginManager) expects an instance of Interop\Container while Symfony\Component\DependencyInjection\ContainerBuilder does not implement this, but rather implements the Psr\Container\ContainerInterface directly.

This same problem also happens with both Pimple and Auryn, also selectable DI Containers. When I set up the project with the same modules, but select the default Zend DI Container it works just fine out of the box. I expected to see the same result when choosing the Symfony DI Container, Pimple, or Auryn in the configuration options, as the create project wizard leads me to believe these are supported DI Containers.

Some additional information, according to composer.lock:

  • zendframework/zend-expressive-skeleton version: 3.0.4
  • symfony/dependency-injection version: v4.0.7
  • container-interop/container-interop: 1.2.0

As a side note: I do not fully understand why the AbstractPluginManager expects an instance of Interop\Container since this is an interface which has been deprecated over a year ago in favour of the PSR-11 Container interface. DI Containers like Symfony, Pimple and Auryn have clearly already caught up with this. As Zend Expressive 3 is so new I expect it to use the PSR-11 interface for the best compatibility with up to date DI Containers.


Originally posted by @olger01 at zendframework/zend-expressive#608

Tutorial - Getting start - suggestion

I've found "generate-factory-for-class" very usefull, but executing it on Windows was a small problem at first.
If I could suggest a small change in this tutorial, I recomend adding a comment saying that correct syntax of this command would be:
.\vendor\bin\generate-factory-for-class "App\Action\TemplateTestAction" > src/App/src/Action/TemplateTestActionFactory.php

The biggest problem was that classname shouldn't be App\\Action\\TemplateTestAction but App\Action\TemplateTestAction. Well, at least in my environment.


Originally posted by @asui at zendframework/zend-expressive#472

HTTP/1.1 response to the Client of 1.0

# create project from zend-expressive-skeleton
composer create-project zendframework/zend-expressive-skeleton .

# run container
docker run --rm -p 8080:80 -v "$PWD:/app" -w "/app" php:apache sh -c '
  a2enmod rewrite
  rmdir /var/www/html
  ln -s /app/public /var/www/html
  exec apache2-foreground
'

# run curl in other terminal, and see response
curl -i -0 http://localhost:8080/

curl request is HTTP/1.0, but zend-expressive has HTTP/1.1 response.

HTTP/1.1 200 OK
Date: Wed, 26 Jul 2017 10:46:48 GMT
Server: Apache/2.4.10 (Debian)
X-Powered-By: PHP/7.1.7
Content-Length: 151
Content-Type: application/json

:

Next, I tried ApacheBench.

ab -c 1 -n 1 http://localhost:8080/

Very very slow.

:
Requests per second:    0.20 [#/sec] (mean)
Time per request:       5021.594 [ms] (mean)
Time per request:       5021.594 [ms] (mean, across all concurrent requests)
:

ApacheBench expect active close of server, but server does not close until KeepAliveTimeout seconds.


This problem can solved by fix response protocol version based on request protocol version.

// pipeline.php

use Psr\Http\Message\ServerRequestInterface;
use Interop\Http\ServerMiddleware\DelegateInterface;

$app->pipe(function (ServerRequestInterface $request, DelegateInterface $delegate) {
    return $delegate->process($request)->withProtocolVersion($request->getProtocolVersion());
});

Originally posted by @ngyuki at zendframework/zend-expressive#502

routes => middleware => multiple actions does not get lazy loaded

Example:
config

    [
        'name'            => 'my.post',
        'path'            => "/my",
        'middleware'      => [
            Action\PostAction::class,
            Action\PostAction2::class, // add another action to react on path
        ],
        'allowed_methods' => ['POST'],
    ],

Im using a middleware (priority PHP_INT_MAX) to catch fatal error (register_shutdown_function).
When im using one action only in the config
and when i force an fatal error in that action
the registered shutdown function gets called.

If im using two actions as shown above
then no registered shutdown function gets called.
The middleware im using wont be invoked/loaded before the action.


Originally posted by @cottton at zendframework/zend-expressive#361

Psalm integration

Feature Request

Q A
QA yes

Summary

As decided during the Technical-Steering-Committee Meeting on August 3rd, 2020, Laminas wants to implement vimeo/psalm in all packages.

Implementing psalm is quite easy.

Required

  • Create a psalm.xml in the project root
  • Copy and paste the contents from this psalm.xml.dist
  • Run $ composer require --dev vimeo/psalm
  • Run $ vendor/bin/psalm --set-baseline=psalm-baseline.xml
  • Add a composer script static-analysis with the command psalm --shepherd --stats
  • Add a new line to script: in .travis.yml: - if [[ $TEST_COVERAGE == 'true' ]]; then composer static-analysis ; fi
  • Remove phpstan from the project (phpstan.neon.dist, .travis.yml entry, composer.json require-dev and scripts)
Optional
  • Fix as many psalm errors as possible.

Mezzio does not work without a router

Bug Report

Q A
Version(s) 3.5.1

Summary

I have use-case where I do not need routes but want to use mezzio.

The Application requires RouteCollector which is provided by the various router services. Due to the lack of an interface, the RouteCollector cannot be stripped away and thus, one has to provide a factory for the RouteCollector even tho the project does not need any routes.

Current behavior

When no router implementation is required by composer (and thus no factory is available for the RouteCollector), mezzio crashes.

Laminas\ServiceManager\Exception\ServiceNotCreatedException: Service with name "Mezzio\Router\RouteCollector" could not be created. Reason: Missing dependency "Mezzio\Router\RouterInterface" for service "Mezzio\Router\RouteCollector"; please make sure it is registered in your container. Refer to the Mezzio\Router\RouteCollector class and/or its factory to determine what the service should return.

How to reproduce

  1. Create a new mezzio application using the create-project syntax as described within documentation
  2. Remove the router you've chosen during setup with composer remove mezzio/<router>
  3. Run application

Expected behavior

Until no route is provided to the application, nothing should happen.
When calling $app->route (or those aliases which wrap that method) on an app without a RouteCollector, an exception should be thrown.

Unable to handle errors in v1

I cannot see a proper stack trace of errors while I'm developing, which is obviously very frustrating.
However, when I switch php error reporting on I can see an exception raised by Diactoros (...Unsupported response reason phrase; must be a string, received NULL...zendframework/zend-diactoros/src/Response.php:185 Stack trace...) , but no trace/indication of where the problem actually occurred, when php error reporting is off then I get a blank screen with server 500 error.

I thought Zend Expressive has default exception and other response handling built in i.e. 404, methodNotAllowed etc, instead of just bombing out on all problems... or is it up to the developer to write this core functionality?
I've wasted so much time searching for examples, but as usual nothing that that works... I cannot believe this is so badly documented (or an architecture flaw in v1?)

I mostly use PHP Slim and it has the above baked in, the developer can also override it with custom handlers...simple and to-the-point. I can unfortunately not use Slim and have to solve this error reporting issue with Zend Expressive.. please help


Originally posted by @TradeSharer at zendframework/zend-expressive#653

Document split for routers and template renders

I just found this in the Expressive v3 project:

Document v3 changes

We need to document version 3. We can begin by creating a new v3 section of the docs based on latest v2, and modifying it to conform to what will actually release with v3.

We may want to consider splitting documentation into discrete repositories as well: pushing router and template renderer docs to the appropriate repositories, etc.

Especially the last part. I'm all in favor of this. I've seen too many notes in those projects that docs need to be updated in zend-expressive.

I'm opening the issue here so we can discuss it and I can close the expressive v3 project.


Originally posted by @geerteltink at zendframework/zend-expressive#594

Description of a manual installation is missing

I'm trying to include zend-expressive in my project, but unsuccessfully.
When i require zend-expressive via console ( composer require zendframework/zend-expressive ), i get the following error:

Your requirements could not be resolved to an installable set of packages.
  Problem 1
    - zendframework/zend-expressive 3.0.0 requires zendframework/zend-httphandlerrunner ^1.0.1 -> satisfiable by zendframework/zend-httphandlerrunner[1.0.1].
    - zendframework/zend-expressive 3.0.1 requires zendframework/zend-httphandlerrunner ^1.0.1 -> satisfiable by zendframework/zend-httphandlerrunner[1.0.1].
    - zendframework/zend-expressive 3.0.2 requires zendframework/zend-httphandlerrunner ^1.0.1 -> satisfiable by zendframework/zend-httphandlerrunner[1.0.1].
    - zendframework/zend-httphandlerrunner 1.0.1 requires psr/http-message-implementation ^1.0 -> no matching package found.
    - Installation request for zendframework/zend-expressive ^3.0 -> satisfiable by zendframework/zend-expressive[3.0.0, 3.0.1, 3.0.2].

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
 - It's a private package and you forgot to add a custom repository to find it

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

Code to reproduce the issue

composer require zendframework/zend-expressive

Expected results

Expected composer to install the package

Actual results

Composer returned an error regarding package dependencies


Originally posted by @itapai at zendframework/zend-expressive#624

Cannot set error handler layout to null

Bug Report

Q A
Version(s) x.y.z

Summary

Current behavior

I will not use layout templates for error pages, so I want to set layout to null for error templates. Using this configuration;
[ 'mezzio' => [ 'error_handler' => [ 'layout' => null ] ] ]
this does not cancel layout. However, instead of null if I use empty string ('') this works. But I don't know if this is right and will break in future versions.
This behaviour is inconsistent with other parts. For example I can cancel global layout with this configuration;
[ 'templates' => ['layout' => null] ]

How to reproduce

[ 'mezzio' => [ 'error_handler' => [ 'layout' => null ] ] ]
does not cancel error handler layout.

Expected behavior

[ 'mezzio' => [ 'error_handler' => [ 'layout' => null ] ] ]
should cancel error handler layout

Allow for mezzio to be run in a sub directory of the web server

Feature Request

Allow for mezzio to be run in a sub directory of the web server, out of the box, without need of configuration.

Q A
New Feature yes
RFC no
BC Break maybe

Summary

When installing mezzio it does not work, out of the box, when running the website in a sub directory.

I found an article on "Cookbook Using Mezzio from a subdirectory", but that contains a series of actions and configurations.

My humble opinion is that it should work in a sub directory out of the box, like for example the Laravel, Symfony and Yii Framework does. Doing so would make it easier for first come users to adapt the framework since it has less restrictions on the development- and production environment in which it runs.

My reason for this opinion is mainly from an educational perspective. When doing education using Mezzio, one can not always expect the students to have their own servers. We for example are using a shared server where the students publish their websites. This can also be thought of as a usability perspective.

I can not say if this request would interfere with other existing features of mezzio. This was just my first experience of using mezzio. I did not see any notes on this requirement while I was browsing the documentation (however I might have missed it...).

How to repeat

  1. I install mezzio and use the defaults.
composer create-project mezzio/mezzio-skeleton app

I access the website and gets this.

2021-04-21_17:30:53_502x90

  1. I reinstall and use Plates template system.

I then get this response.

2021-04-21_17:33:10_654x390

Missing good examples of configuration template paths for laminas-view in mezzio

Hi guys!
I'm trying to integrate mezzio/mezzio-laminasviewrenderer into our mezzio project which was only api oriented. I need laminas-view templates to generate html code for emails.
I have read documentation from this page https://docs.mezzio.dev/mezzio/v3/features/template/laminas-view/
And there is an example of rendering html like this one

$content = $renderer->render('blog/entry', [
    'layout' => 'layout::blog',
    'entry'  => $entry,
]);

What is 'blog/entry'???
What is 'layout::blog'???
How to configure them and how to attach them to real phtml files?
I was trying to understand source code from /vendor/mezzio/mezzio-laminasviewrenderer/src/LaminasViewRendererFactory.php . It contains this example:

 * <code>
 * 'templates' => [
 *     'extension' => 'default template file extension',
 *     'layout' => 'name of layout view to use, if any',
 *     'map'    => [
 *         // template => filename pairs
 *     ],
 *     'paths'  => [
 *         // namespace / path pairs
 *         //
 *         // Numeric namespaces imply the default/main namespace. Paths may be
 *         // strings or arrays of string paths to associate with the namespace.
 *     ],
 * ]
 * </code>

Can somebody show me and example of configuring 'paths'?
Looks like it should be like this:

'templates' => [
      'paths'  => [
	      [
		      'blog/entry' => '/path/to/blog/entry.phtml'
	      ]
      ],
]

or

'templates' => [
      'paths'  => [
	      'some::namespace' => [
		      'blog/entry' => '/path/to/blog/entry.phtml'
	      ]
      ],
  ]

Am I correct? Is there a good example with source code how to use laminas-view with mezzio?

Create `Mezzio\ApplicationPipeline` implementation for better static code analysis

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

In this package, Mezzio\ApplicationPipeline is a service identifier to retrieve the assembled middleware pipeline for a mezzio project which does not actually represents a class.

This pipeline is consumed by these classes in a mezzio project:

That pipeline gets assembled in:

return new MiddlewarePipe();

And registered in:

ApplicationPipeline::class => Container\ApplicationPipelineFactory::class,


Retrieving this pipeline via a PSR-11 is quite annoying due to the fact that neither an IDE is able to auto-complete the typed service name nor a static-analysis tool is able to understand what is happening.

My suggestion would be to create a class called ApplicationPipeline which implements MiddlewarePipeInterface (which implements both RequestHandlerInterface and MiddlewareInterface) and thus allow factories to retrieve that pipeline via:

  1. Mezzio\ApplicationPipeline class-string
  2. (optional) Psr\Http\Server\RequestHandlerInterface class-string (alias to Mezzio\ApplicationPipeline)

This would allow us to properly fetch the application pipeline from within the ApplicationFactory and the RequestHandlerRunnerFactory:

$container->get(ApplicationPipeline::class),

$container->get(ApplicationPipeline::class),

Empty response with WhoopsErrorResponseGenerator and zend-expressive-swoole

I'm just playing around with expressive and zend-expressive-swoole and noticed that given the WhoopsErrorResponseGenerator is configured as ErrorResponseGenerator no response body will be sent. The default ErrorResponseGenerator however works fine.

Expected results

Get response body generated by WhoopsErrorResponseGenerator

Actual results

empty response on errors.


Originally posted by @iwyg at zendframework/zend-expressive#635

Replace `RequestHandlerRunner` factory with `RequestHandlerRunnerInterface` factory

We have to remove the alias RequestHandlerRunnerInterface introduced in #110 and instead add it to the factories.
This should also remove the RequestHandlerRunner factory so that the RequestHandlerRunner service is not available via the container anymore.

This introduces a BC break but will provide better capabilities for projects which want to decorate the runner.


This can go to 3.11.x indeed, but we should change this from aliases to factories in 4.x since RequestHandlerRunner should not be requestable as a service from the container.

Since delegators only work on services, this would be a BC break for sure and therefore I'd like to keep this in mind and thus dropping it here. Creating a new issue for 4.x from this comment to keep track.

Originally posted by @boesing in #110 (comment)

Support for laminas-httphandlerrunner 2.x versions

Feature Request

Support for laminas-httphandlerrunner 2.x versions

Q A
New Feature yes
RFC no
BC Break yes?

Summary

It is possible have support in composer both httphandlerrunner major version 1.x || 2.x Or it is should be new major release (4.0) with 2.x only??

[Question] $request->getParsedBody() returns empty array using PUT/PATCH methods

I'm having difficulty in parsing the $request->getParsedBody() for PUT/PATCH method - it only returns empty array.

I've enabled Body Parsing Middleware on my controller and it works with POST method.

https://docs.zendframework.com/zend-expressive/features/helpers/body-parse/

I'm trying to implement the REST Controller by Alejandro Celaya

https://blog.alejandrocelaya.com/2016/06/24/dispatch-rest-like-requests-with-a-single-controller-class-in-zend-expressive/

Appreciate your input here. Thanks in advance.


Originally posted by @gabbydgab at zendframework/zend-expressive#371

new routed middleware definitions

Feature Request: new middleware definition 'FQCN::method' and ['FQCN', 'method']

Q A
New Feature yes
RFC no
BC Break no

Summary

It would be nice to be able to define "controller-like" handlers for multiple routes without resorting to:
https://docs.mezzio.dev/mezzio/v2/cookbook/using-routed-middleware-class-as-controller/#handling-multiple-routes-in-a-single-class

At present stage middleware definitions such as:

$app->route('/news/article/create', [News\ArticleController::class, 'create']);
$app->route('/news/article/update/{id}', [News\ArticleController::update');

are treated as callable-handlers and obviously do not work.

This would also remove the need for setting an extra 'action' request attribute and maybe cleaner route definitions
(example updated with allowed_methods on 2020-04-13)

// file config/autoload/routes.global.php
return [
   // ...
    'routes' => [
        // article creation handling submitted form data
        'news/article/create' => [
            'path' => 'news/article/create',
            'middleware' => [News\ArticleController::class, 'create'],
            // or
            // 'middleware' => 'News\ArticleController::create',
            'allowed_methods' => ['POST'],
        ],
        // show article update form
        'news/article/edit' => [
            'path' => 'news/article/edit/{id}',
            'middleware' => [News\ArticleController::class, 'update'],
            'allowed_methods' => ['GET'],
        ],
        // article update handling submitted form data
        'news/article/update' => [
            'path' => 'news/article/update/{id}',
            'middleware' => [News\ArticleController::class, 'update'],
            'allowed_methods' => ['POST', 'PATCH', 'PUT'],
        ],
        // article deletion
        'news/article/delete' => [
            'path' => 'news/article/delete/{id}',
            'middleware' => [News\ArticleController::class, 'delete'],
            'allowed_methods' => ['POST', 'DELETE'],
        ],
        // instead of the following
        // this may look simpler but:
        // 1. We have only 1 route and we have to add a subst param ['action' => 'create'] in UrlHelper
        // 2. We to examine the request action-attribute in the controller(handler) handle method to reroute the request to internal method
        'news/article' => [
            'path' => 'news/article/{action:create|update|delete}(/{id})',
            'options' => [
                'defaults' => [
                    'action' => 'whatever',
                ],
            ],
            'middleware' => News\ArticleController::class,
        ],
    ],
];

The idea is to have a LazyControllerMiddleware that handles these 2 types of middleware definitions. The LazyControllerMiddleware would fetch the controller(handler) from the container on demand, create a wrapping middleware and run the defined controller-method in the wrapper process() method.

This would be useful when different handlers have the same dependencies (e.g. crud write-handlers).

Anyone else likes the idea?

kind regards,
maks

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Repository problems

These problems occurred while renovating this repository. View logs.

  • WARN: Use matchDepNames instead of matchPackageNames

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

composer
composer.json
  • php ~8.1.0 || ~8.2.0 || ~8.3.0
  • fig/http-message-util ^1.1.5
  • laminas/laminas-httphandlerrunner ^2.1
  • laminas/laminas-stratigility ^3.5
  • mezzio/mezzio-router ^3.7
  • mezzio/mezzio-template ^2.2
  • psr/container ^1.0||^2.0
  • psr/http-factory ^1.0
  • psr/http-message ^1.0.1 || ^2.0.0
  • psr/http-server-middleware ^1.0
  • webmozart/assert ^1.10
  • filp/whoops ^2.15.4
  • laminas/laminas-coding-standard ~2.5.0
  • laminas/laminas-diactoros ^3.3.0
  • laminas/laminas-servicemanager ^3.22.1
  • mezzio/mezzio-aurarouter ^3.7
  • mezzio/mezzio-fastroute ^3.11
  • mezzio/mezzio-laminasrouter ^3.9
  • phpunit/phpunit ^10.5.9
  • psalm/plugin-phpunit ^0.18.4
  • vimeo/psalm ^5.21.1
github-actions
.github/workflows/continuous-integration.yml
.github/workflows/docs-build.yml
.github/workflows/release-on-milestone-closed.yml

  • Check this box to trigger a request for Renovate to run again on this repository

PHP 8.0 support

Feature Request

Q A
New Feature yes

Summary

To be prepared for the december release of PHP 8.0, this repository has some additional TODOs to be tested against the new major version.

In order to make this repository compatible, one has to follow these steps:

  • Modify composer.json to provide support for PHP 8.0 by adding the constraint ~8.0.0
  • Modify composer.json to drop support for PHP less than 7.3
  • Modify composer.json to implement phpunit 9.3 which supports PHP 7.3+
  • Modify .travis.yml to ignore platform requirements when installing composer dependencies (simply add --ignore-platform-reqs to COMPOSER_ARGS env variable)
  • Modify .travis.yml to add PHP 8.0 to the matrix (NOTE: Do not allow failures as PHP 8.0 has a feature freeze since 2020-08-04!)
  • Modify source code in case there are incompatibilities with PHP 8.0

How can I pass locale to Twig extension?

I have made routes and locale middleware with this Cookbook:
setting-locale-depending-routing-parameter.md

Now I wonder how I can pass the locale to Twig Extension which I use to create function {{ __('translate me') }}

Twig Extension is added in config/autoload/templates.global.php like this:

return [
    'dependencies' => [
        'factories' => [
            Twig_Environment::class => TwigEnvironmentFactory::class,
            TemplateRendererInterface::class => TwigRendererFactory::class,
            TranslationExtension::class => TranslationExtension::class,
        ],
    ],

    'templates' => [
        'extension' => 'html.twig',
    ],

    'twig' => [
        'cache_dir'      => 'data/cache/twig',
        'assets_url'     => '/',
        'assets_version' => null,
        'extensions'     => [
            // extension service names or instances
            TranslationExtension::class
        ],
        'runtime_loaders' => [
            // runtime loader names or instances
        ],
        'globals' => [
            // Variables to pass to all twig templates
        ],
        'timezone' => 'Europe/Helsinki',
    ],
];


Originally posted by @back-2-95 at zendframework/zend-expressive#524

Add Album tutorial to docs

I really love Zend\Expressive so far. To really get in rolling for beginners, I would love to see a tutorial like the Album tutorial for a Zend\Mvc project. It is really nice to see the examples, but beginners will also look for help how to structure their applications based on Zend\Expressive properly.

Any ideas and thoughts about this?


Originally posted by @RalfEggert at zendframework/zend-expressive#176

bin/mezzio-tooling is incompatible with mezzio/mezzio-tooling v2

Bug Report

Q A
Version(s) 3.11.0

Summary

mezzio-tooling installation fails on this line

exit(1);
. This is of course because there is no "php" section in https://github.com/mezzio/mezzio-tooling/blob/2.7.x/composer.json. Was this working at some point or how is this meant to work?

How to reproduce

➜  criticker-api git:(master) ✗ php vendor/mezzio/mezzio/bin/mezzio-tooling
Installing mezzio-tooling
Using version ^2.6 for mezzio/mezzio-tooling
./composer.json has been updated
Running composer update mezzio/mezzio-tooling
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
Generating autoload files
composer/package-versions-deprecated: Generating version class...
composer/package-versions-deprecated: ...done generating version class
60 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found


Installed tooling package, but package does not contain script information?
Check your installation, and follow the migration documentation to use the tooling.

Fatal error after creating a mezzio project with "composer create-project mezzio/mezzio-skeleton"

Bug Report

Q A
Version(s) 3.2.1

Summary

When installing the skeleton of mezzio using the following command:

composer create-project mezzio/mezzio-skeleton .

I get an error when loading the home page:

image

How to reproduce

  • Run composer create-project mezzio/mezzio-skeleton .
  • Run php -S 0.0.0.0:9000 -t public/

Also, the problem was solved running composer update.

Expected behavior

I expect the following home page:

image

Zend Expressive vs Zend Framework 3 vs Zend Apigility for REST API with Swagger docs?

Hi all,

I have read zendframework/zend-expressive#342 and I still have a few questions. Firstly, let me describe the scenario.

Current situation
Web application written in Zend Framework 1. There are two modules in the ZF1 app structure:

  • "default" model used for the publicly accessible website

  • "admin" model used for web administrators (accessible only by employees of the company) to update the website content and much more things covering the internal processes of the mentioned company

The future
Convert the "default" module to an rest API to let 3rd party companies create the public website using this to be developed API to deliver the content.
The "admin" module will stay untouched for now.

The question
I know I could probably simply tweak the old ZF1 "default" module to serve as an API (remove all the views and update all the controllers to return some JSON structure). But I would like to take this as an opportunity to get my hands on something new. So I am thinking about ZF3, Expressive or Apigility.

I want to deliver simple REST API which would basically serve to:

  • deliver content (texts, images) to the website
  • offer form validation for the website
  • creating few things in the connected DB via posting several forms on the website

What I believe is a must have is a self-generated documentation (I would prefer Swagger) because the API will be used by 3rd party companies to create/redesign the website.

Which of the Zend "frameworks" mentioned above is suited for such a task? What do you guys think?

I pretty much like the Zend Expressive as it is kind of minimalistic and can be tweaked to whatever needed however I am not able to find out whether there is a swagger component. I have found Swagger component for ZF3. And Apigility is a bit mystery to me. It seems like it is a online tool for creating rest apis which sounds interesting and scary at the same time as I cannot imagine myself writing a controller code in a browser but I might be missing something about Apigility.

Thanks you very much and if you want me to clarify anything just let me know.


Originally posted by @starkskalle at zendframework/zend-expressive#665

Missing documentation for UrlHelper (reuse_result_params)

Bug Report

Q A
Version(s) x.y.z

Summary

Missing documentation for UrlHelper and reuse_result_params - no mention of reuse_result_params in current documentation.

Current behavior

I was looking to generate canonical url's for blog posts, using $this->serverUrl($this->url('blog.list')), the default behaviour is to re-use route params, so URLs were generating route params. Instead of generating '/blog/' I was getting '/blog/category/videos' for example.

I was able to generate the correct URLs using:
$this->serverUrl($this->url('blog.list', [], [], null, ['reuse_result_params' => false]))

How to reproduce

Expected behavior

[Question] Doc about debugbar in a programmatic_pipeline context

Following the doc about debugbars, the php-middleware/php-debug-bar neither bitExpert/prophiler-psr7-middleware didn't work in a 'programmatic_pipelines' context.

What is the recommended way to pipe middleware only for development ?

For now I've ended up adding them in the config/pipeline.php file:

$app->pipe(ErrorHandler::class);

$debug = $app->getContainer()->get('config')['debug'] ?? false;
if ($debug) {
    /* example with phpdebugbar */
    $debugBarFactory = new \PhpMiddleware\PhpDebugBar\PhpDebugBarMiddlewareFactory();
    $middleware = $debugBarFactory();
    $app->pipe($middleware);

    /* example with prophilermiddleware */
    $prophiler  = new \Fabfuel\Prophiler\Profiler();
    $toolbar    = new \Fabfuel\Prophiler\Toolbar($prophiler);
    $middleware = new \bitExpert\Http\Middleware\Psr7\Prophiler\ProphilerMiddleware($toolbar);
    $app->pipe($middleware);
}

$app->pipe(ServerUrlMiddleware::class);
//...

Not sure if it's a good practive. BTW both debugbars looks pretty minimal. Is there any plan to have the ZendDeveloperTools toolbar for expressive ?

Note, for PHP7 and ProphilerMiddleware, you add:

$ composer require --dev fabfuel/prophiler:dev-feature/php7 bitexpert/prophiler-psr7-middleware

Originally posted by @belgattitude at zendframework/zend-expressive#488

Can not create links from routes with optional parameters

Bug Report

Q A
Version mezzio/mezzio 3.2.2
Version laminas/laminas-router 3.3.2
PHP 7.2.31

Summary

Current behavior

Actually I have an Zend MVC Application with the following routing:

return [
    'routes' => [
        'wizard' => [
            'type' => Segment::class,
            'options' => [
                'route'    => '/wizard/[:embed/]:id/:sessionId',
                'constraints' => [
                    'id'    => '[1-9][0-9]*',
                    'embed' => 'embed',
                ],
                'defaults' => [
                    'controller' => Controller\IndexController::class,
                    'id'         => 1,
                ],
            ],
        ]

I'm using this call to generate an Uri in a view script:

$this->url('wizard', ['id' => 1, 'embed' => null, 'sessionId' => 'os09t2ujphehcbvp7nr7fgs5ei'])

The generated Uri is "/wizard/1/os09t2ujphehcbvp7nr7fgs5ei".

I'm trying to rewrite that Application to an Mezzio Application.

The new Route configuration is:

$wizardRoute = $app->post(
        '/wizard/[:embed/]:id/:sessionId',
        [
            MandantHandler::class,
            SessionMiddleware::class,
            StartFormHandler::class,
        ],
        'wizard'
    );

    $wizardRoute->setOptions(
        [
            'constraints' => [
                'id'    => '[1-9][0-9]*',
                'embed' => 'embed',
            ],
            'defaults' => [
                'id' => 1,
                'embed' => '', // <-- this is nessesary to get this working
            ],
        ]
    );

The new Call in a view script has to be:

$this->url('wizard', ['id' => 2, 'embed' => '', 'sessionId' => '2d5d501b4a0f1d8caa171258e8821a54'])

The generated Uri is now "/wizard//2/2d5d501b4a0f1d8caa171258e8821a54". (With double Slash)

If I set the "embed" parameter to null or don't set default, I get this Exception:

Laminas\Router\Exception\InvalidArgumentException thrown with message "Missing parameter "embed""

Stacktrace:
#63 Laminas\Router\Exception\InvalidArgumentException in /home/developer/projects/mezzio/vendor/laminas/laminas-router/src/Http/Segment.php:310
#62 Laminas\Router\Http\Segment:buildPath in /home/developer/projects/mezzio/vendor/laminas/laminas-router/src/Http/Segment.php:329
#61 Laminas\Router\Http\Segment:buildPath in /home/developer/projects/mezzio/vendor/laminas/laminas-router/src/Http/Segment.php:424
#60 Laminas\Router\Http\Segment:assemble in /home/developer/projects/mezzio/vendor/laminas/laminas-router/src/Http/Part.php:208
#59 Laminas\Router\Http\Part:assemble in /home/developer/projects/mezzio/vendor/laminas/laminas-router/src/Http/TreeRouteStack.php:371
#58 Laminas\Router\Http\TreeRouteStack:assemble in /home/developer/projects/mezzio/vendor/mezzio/mezzio-laminasrouter/src/LaminasRouter.php:128
#57 Mezzio\Router\LaminasRouter:generateUri in /home/developer/projects/mezzio/vendor/mezzio/mezzio-helpers/src/UrlHelper.php:106
#56 Mezzio\Helper\UrlHelper:__invoke in /home/developer/projects/mezzio/vendor/mezzio/mezzio-helpers/src/UrlHelper.php:129
#55 Mezzio\Helper\UrlHelper:generate in /home/developer/projects/mezzio/vendor/mezzio/mezzio-laminasviewrenderer/src/UrlHelper.php:47
...
#2 Laminas\HttpHandlerRunner\RequestHandlerRunner:run in /home/developer/projects/mezzio/vendor/mezzio/mezzio/src/Application.php:82
#1 Mezzio\Application:run in /home/developer/projects/mezzio/public/index.php:29
#0 {closure} in /home/developer/projects/mezzio/public/index.php:30

How to reproduce

Expected behavior

It is possible to set an optional Parameter to null and the Parameter is not in the generated Uri.

PHP 8.1 Support

Feature Request

Q A
New Feature yes
RFC no
BC Break no

Summary

This issue aims to track the PHP 8.1 support addition to the project. Happy to help on this issue if it's necessary.

Move router integration tests to router packages

RFC

Q A
Proposed Version(s) 3.7.0
BC Break? No

Goal

To unblock PHP 8.1 support from this package, we should remove all router integration tests and only do unit tests when it comes to integration tests (and/or use our own laminas-router where we actually can always provide patches to be compatible with new versions - e.g. PHP or major versions of this package).

Background

mezzio/mezzio-aurarouter does not support PHP 8.1 yet. To provide proper 8.1 support (without deprecation warnings), we would have to provide patches to https://github.com/auraphp/Aura.Router
To avoid having that huge amount of work until we can get this package ready for 8.1, we should move all integration tests to the related components.

Considerations

Users wont have any impact on this as we only require these packages for integration tests.

Proposal(s)

  1. Remove all integration tests from here (or keep those we actually can maintain by ourselves)
  2. Provide support for PHP 8.1

Appendix

If we do want to keep that package, we should at least remove integration tests from this package and port them to the router component.

Using ApplicationConfigInjectionDelegator more than once (in multiple modules simultaneously) results results in a DuplicateRouteException.

Bug Report

Q A
Version(s) 3.6.0 (likely earlier as well)

Summary

Using ApplicationConfigInjectionDelegator more than once (in multiple modules simultaneously) results results in a DuplicateRouteException. I found out about this after being contacted by a reader of Mezzio Essentials.

Current behavior

If you load the ApplicationConfigInjectionDelegator in more than one module in a Mezzio project, such as in the example below, in the module's ConfigProvider, then a DuplicateRouteException is thrown.

    public function getDependencies() : array
    {
        return [
            // ... existing configuration
            'delegators' => [
                Application::class => [
                    ApplicationConfigInjectionDelegator::class,
                ],
            ],
        ];
    }

This happens because ApplicationConfigInjectionDelegator::injectRoutesFromConfig calls Mezzio\Application::route, which ultimately throws a DuplicateRouteException because it injectRoutesFromConfig doesn't check if a route is in the routing table before attempting to add the existing routing table to the routing table. I don't know if this is the intended functionality, but thought that if a route was added, that it would overwrite an existing one.

How to reproduce

Add the above code snippet in more than one module. You don't need to add any further configuration.

Expected behavior

That if there are no, actual, duplicate routes, that no DuplicateRouteException would be thrown.

development config symlink not deleted after installing as with --no-dev option

Bug Report

after running
composer install --no-dev
config/autload/development.local.php symlink still remains .
My project crashes with error message "Uncaught Error: Class 'Whoops\Run' ".
I have to manually delete "development.local.php" after install.
May be there is a problem with my workflow. I sync development files to deployment space and run composer install --no-dev afterwards. But at least switching from development to no-dev should work.

Q A
Version(s) x.y.z

Summary

Current behavior

composer install
composer install --no-dev
config/autload/development.local.php symlink still remains .

How to reproduce

Expected behavior

composer install
composer install --no-dev
config/autload/development.local.php should not exist

Configure FormElementManager

I have a little module that configures the FormElementManager like this:

return[
    'form_elements' => [
        'factories' => [
            PriceFieldset::class        => PriceFieldsetFactory::class,
            ProductFormInterface::class => ProductFormFactory::class,
        ],
    ],
];

This config is loaded by a ConfigProvider class and loaded by the ConfigManager in the /config/config.php file like this:

$configManager = new ConfigManager(
    [
        Zend\Form\ConfigProvider::class,
        Product\ConfigProvider::class,
        new PhpFileProvider($pattern),
    ],
    $cachedConfigFile
);

When I want to access the ProductFormInterface::class from the FormElementManager it is not found. I need to these lines to the /config/container.php file to get this running.

$container = new ServiceManager();
(new Config($config['dependencies']))->configureServiceManager($container);

// Inject config
$container->setService('config', $config);

/** @var FormElementManagerV3Polyfill $formElementManager */
$formElementManager = $container->get('FormElementManager');
$formElementManager->configure($config['form_elements']);

return $container;

What am I doing wrong? I don't think this is a wanted behaviour. In my module I also have some validators, filters, hydrators and input filters as well. Currently, I need to add the configuration manually for every specialized service managers.


Originally posted by @RalfEggert at zendframework/zend-expressive#387

Path segregation - pipeline middleware - config-driven

@weierophinney

Good morning,

I've an expressive application with a config-driven pipeline. That application exposes different UI levels such as /admin, /reseller and /client, among others...

Right now, I've a specific pipeline middleware that I want to execute only for specific paths:

...
protected function getPipeline()
{
    return [
        [
            'path' => '/admin',
            'middleware' => \Zend\Expressive\Navigation\Middleware\NavigationMiddleware::class
        ],
        [
            'path' => 'reseller',
            'middleware' => \Zend\Expressive\Navigation\Middleware\NavigationMiddleware::class
        ],
        [
            'path' => '/client',
            'middleware' => \Zend\Expressive\Navigation\Middleware\NavigationMiddleware::class
        ],
    ];
}
...

This is working but, I would rather be able to do something like this:

...
protected function getPipeline()
{
    return [
        [
            'paths' => ['/admin', '/reseller', '/client'],
            'middleware' => \Zend\Expressive\Navigation\Middleware\NavigationMiddleware::class
        ],
    }
}
...

Of course, I could use a custom delegator but I think this could be integrated in the default \Zend\Expressive\Container\ApplicationConfigInjectionDelegator delegator as follows:

...
    public static function injectPipelineFromConfig(Application $application, array $config) : void
    {
        if (empty($config['middleware_pipeline'])) {
            return;
        }

        // Create a priority queue from the specifications
        $queue = array_reduce(
            array_map(self::createCollectionMapper(), $config['middleware_pipeline']),
            self::createPriorityQueueReducer(),
            new SplPriorityQueue()
        );

        foreach ($queue as $spec) {
            $paths = $spec['path'] ?? ($spec['paths'] ?? '/');
            foreach((array) $paths as $path) {
                $application->pipe($path, $spec['middleware']);
            }
        }
    }
...

instead of

....
    public static function injectPipelineFromConfig(Application $application, array $config) : void
    {
        if (empty($config['middleware_pipeline'])) {
            return;
        }

        // Create a priority queue from the specifications
        $queue = array_reduce(
            array_map(self::createCollectionMapper(), $config['middleware_pipeline']),
            self::createPriorityQueueReducer(),
            new SplPriorityQueue()
        );

        foreach ($queue as $spec) {
            $path = $spec['path'] ?? '/';
            $application->pipe($path, $spec['middleware']);
        }
    }
....

Thank you.


Originally posted by @nuxwin at zendframework/zend-expressive#652

Explanation of installation choices

Summary: explain the pros/cons, speed and other differences between the choices we have.

When I first looked at zend expressive I was impressed but confused, It looked nice, but I didn't know what happened with mvc nor the difference between these two choices, and I also looked at all the choices I had when it came to view, routing etc. And did not know what to pick or what the difference was. A Routing choices page where the differences are listed, as well as a template choices page in the getting started section.


Originally posted by @AndersMadsen at zendframework/zend-expressive#512

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.