Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path segregation - pipeline middleware - config-driven #4

Open
weierophinney opened this issue Dec 31, 2019 · 3 comments
Open

Path segregation - pipeline middleware - config-driven #4

weierophinney opened this issue Dec 31, 2019 · 3 comments

Comments

@weierophinney
Copy link
Contributor

@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

@weierophinney
Copy link
Contributor Author

We don't recommend usage of config-driven routes or pipelines at this point; starting in Expressive 2, we began moving away from using them in examples, and we've discussed deprecating the feature. I know some people swear by them, but it's a complicated feature, and easy to misconfigure. However, if you want to submit a pull request (which will require tests and documentation), I'll review. (We may separate the feature into a standalone package later, so new features will continue to live.)


Originally posted by @weierophinney at zendframework/zend-expressive#652 (comment)

@weierophinney
Copy link
Contributor Author

@weierophinney

some people swear by them

We are one of them. You should really avoid opinionated implementations. This was the mistake you have made with your MVC implementation. Zend Expressive is really cool as micro-framework and a great alternative to symfony but if you start forcing developers to follow a single road, that will make it unusable or a bad choice for some developers.

We prefer a config-driven pipeline rather than a pipeline programmatically configured. This is a choice we've made because we want make the configuration close to our modules.

Please don't force us to configure our pipelines and/or routes programatically by deprecating the feature, even through, we could always create our own delegator. If you deprecate that feature which is not so complicated to understand, you will really make some of your supporters unhappy.

The major problem with the programmatically approach is that the configuration is not close to the modules. When we setup our OPTIONAL modules, which are close to our application, we want just have to inject their configuration providers, nothing helse. Having to add each module's pipeline/route configurations programatically is really a pain for us and for our end-users.

I'll see if I can contribute a bit more. Right now, I'm developing a Zend helper extension for Plates, extension that composes an helper plugin manager to provide Zend view helpers-like (doctype, navigation ...) in Plates templates. As you surely know already, the major drawback with Plates extensions is that those need to be created on registration. Registering a single helper extension that composes an helper plugin manager solve that issue as the helpers are lazy-created.

Thank you.


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

@weierophinney
Copy link
Contributor Author

You should really avoid opinionated implementations. This was the mistake you have made with your MVC implementation. Zend Expressive is really cool as micro-framework and a great alternative to symfony but if you start forcing developers to follow a single road, that will make it unusable or a bad choice for some developers.

We have to choose carefully where we spend our time maintaining code and educating users. While I appreciate that the config-driven approach is useful to a number of people, the number of support questions we had to field based on them was disproportionate, which was why we moved away from the feature.

This sort of feature is quite easy for us to separate into its own package, however, and we could hand off maintenance of that to interested users. This would be the best of both worlds, I feel, as those who want the feature can install the package and use the support, and we can still direct folks to the explicit routing/pipeline approach we document initially.


Originally posted by @weierophinney at zendframework/zend-expressive#652 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant