Automatic Routing
Created 6 years ago by ryanthompsonSomething that is SUPER wasteful with resources and just not necessary.. the majority of our routing.
The idea here is to automate CRUD and define a best case for control panel routing. Here is my proposal:
admin/* // Engages automatic routing
admin/{slug} // Defines the module to use which will use same name stream for controller by default (pages/pages), otherwise first stream defined if none match the namespace/slug
admin/{slug}/{stream} // Defines the stream to access CRUD for based on the slug / namespace and the index method.
admin/{slug}/{stream}/{action} // Defines all as well as the controller action
Anything past this it will look into subdirectories, then a controller, then index method OR method if provided.
Let's open this up for discussion and point out any best cases you know of and pick it apart!
https://pyrocms.com/forum/channels/roadmap/manual-loader
https://pyrocms.com/forum/channels/roadmap/automatic-routing
Just opened up a couple roadmap discussions on this. I can push up initial code I've got lying around at home later tonight if anyone is open to digging in and helping test / profile.
A very basic routing for that. I'm using a anonymous function but it should be move in a class (else it cannot be cached).
$router->any(
'admin/{module}/{stream?}/{action?}/{id?}',
function ($module, $stream = null, $action = null, $id = null) use ($router) {
if (!$module = app('module.collection')->get($module)) {
abort(404);
} else {
$namespace = (new \ReflectionClass($module))->getNamespaceName();
}
if (!$stream) {
// TODO: How to make that generic?
$stream = 'contents';
}
$controller = vsprintf('%sController', [ucfirst($stream)]);
if (!$action) {
$action = 'index';
}
$action = vsprintf('%s\Http\Controller\Admin\%s@%s', [
$namespace,
$controller,
$action,
]);
$route = $router->current();
return $route
->uses($action)
->run();
}
);
The only thing we currently cannot guess is the default $stream
if we are on the default route (e.g. /admin/contents
).
@frednwt I think this might be best served somewhere earlier up the request chain right? (see last line here for my concern). Like near/in the kernel. But yes you'd have to check for a controller regardless - there will be two class checks I think. One for the literal path to class mapping. And one for the use case where stream == module
so no stream would be listed in the URI.
I would also like to allow crawling into other controller directories like Admin/Api/Controller
if the path indicated it..
So, is this routed first? Last? How do you deal with when the CRUD controller stuff already exists? I would assume this needs to be first.
Right we can just stream == module
. It may not be always true but it is probably the best. And maybe adding somewhere in the Module a $defaultStream = null
that can be override if needed?
No idea how to manage other directories. It will be tricky. Maybe using some naming convention like /admin/contents/api-contents/create
. But using another /
will be complicated.
For the order, I'm currently routing it as last. To be sure no custom routes override. And my routing is more something like:
$controller = vsprintf('%s\Http\Controller\Admin\%s', [
$namespace,
$controller,
]);
if (!class_exists($controller)) {
$controller = 'App\Http\Controller\Admin\BreadController';
}
$action = vsprintf('%s@%s', [
$controller,
$action,
]);
Then every admin controllers extends the BreadController
.
This is done and in 3.7 - HUGE thanks to you @frednwt thank you!