slimphp / Slim

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
http://slimframework.com
MIT License
11.94k stars 1.95k forks source link

Allow overriding routes with the same name and method #1938

Closed alexweissman closed 7 years ago

alexweissman commented 8 years ago

I brought this up in FastRoute, but they seemed to think that the additional complexity required was outside their scope. But, perhaps not outside of Slim's scope!

Basically, it would be good to have some way to override or redefine an existing route, for example in an application that supports plugins. Because routes are matched against regular expressions, there could be some syntax for explicitly overriding one pattern with another, more specific route:

$app->get('/foo/bar/.*', ...)->extends('/foo/.*');

geggleto commented 8 years ago

This would need to be a v4 change I think...

So more or less you are looking for something like...

$app->get('/foo/bar/.*', ...)->extends('/foo/.*');

Is the same thing as ...

$app->get('/foo/bar/.*', ...);
$app->get('/foo/.*', ...)
alexweissman commented 8 years ago

Well, my main interest for now is to be able to override exact-match routes:

core.php

$app->get('/foo/.*', ...)

plugin.php

// Overrides the definition in core.php
$app->get('/foo/.*', ...)

The ability to override or extend with more specific routes would be nice, but yeah that could wait until Slim 4.

geggleto commented 8 years ago

Well I guess we could provide a Removal function in the router currently... that wouldn't be a BC break so it could be included in 3.x ... then using the router I think you could be able to scan the router to see if it already exists and remove/replace as required.

alexweissman commented 8 years ago

yeah, that would probably help a bit. It would be better if overriding were built-in though, because otherwise I am essentially replicating Slim's wrapper and list of routes with yet another list :wink:

alexweissman commented 8 years ago

It looks like it would be pretty easy to do, actually. In this function: https://github.com/slimphp/Slim/blob/3.x/Slim/Router.php#L156-L158

All we'd need to do is check if a route with the same methods, pattern, and group already exists, and then replace it in $this->routes with the same identifier, rather than incrementing to a new identifier.

Some clever indexing when adding routes (for example, a unique signature) would make this more efficient as a simple array lookup, so we don't end up with an O(n^2) complexity.

alexweissman commented 8 years ago

Ok, I've come up with a very basic way to support overriding exact-match routes, by overriding Router::map: https://github.com/userfrosting/UserFrosting/blob/dev/app/core/src/Router.php

Unfortunately, it only allows overriding routes via an exact match of methods and pattern. If for example, you define a multi-method route earlier (e.g. [GET, POST]), you wouldn't be able to override just GET later on - you'd have to redefine the entire [GET, POST] route. The same goes for overriding a subset of a wildcard pattern.

akrabat commented 7 years ago

I can't see us adding this to Slim. We have methods that allow you to remove a route and replace a route's callable.