This is a proposal for a more convenient route configuration, because we always do the same things when setting up our Slim $app:
$route = $app->get( … ) or $app->map(["GET", "POST"], …)$route->setName('hello')$route->add( … )Let's imagine a two-dimensional array like this:
$routes = array(
"index" => array(
"url" => "/",
"via" => [ "GET" ],
"controller" => "IndexPageService",
"middleware" => []
),
"contact" => array(
"url" => "/contact",
"via" => [ "GET", "POST" ],
"controller" => "ContactPageService",
"middleware" => [ "RouteMiddlewareService", "OtherFancyStuff" ]
),
// ... more ...
)
…we then simply pass each item to a new route method in $app, like so:
foreach ($routes as $name => $route_data):
$app->route( $name, $route_data );
endforeach;
The new route method roughly outlined:
class App
{
/**
* Most generic route: Just GET, no middleware stuff.
*/
public $default_route_data = array(
"via" => [ "GET" ],
"middleware" => [ ]
);
/**
* @return RouteInterface
*/
public function route( string $name, array $route )
{
// Glue data
$route_data = array_merge($this->default_route_data, $route);
extract( $route_data ); # Readability hack
// Create named route instance,
// add route middleware
$route = $this->app->map($via, $url, $controller);
$route->setName($name);
foreach( $middleware as $mw ):
$route->add($mw);
endforeach;
return $route;
}
}
Conclusion:
What do you think?
Best regards,
Carsten.
I think in general, if you have to add a comment that contains the word 'hack', you are doing something wrong
IMHO Nobody will take the "hack" word too literally. The above was meant as a _roughly outline_ … did'nt want to trigger you or someone else. Sorry for that :beers:
Alright, no offense taken, but I would like to argue against some of the ideas/methods:
extract obfuscates the code. the function definition array $route doesn't tell anything specific,$route = $this->app->map($via, $url, $controller); it is not obvious where the $url is coming from; maybe add all options to an example or update the default_route_dataI would either go through the route definition array (key by key) and do what needs to be done with them, or define a simple RouteDefinition class that handles the array and use that in the following steps.
I like the idea of separating the configuration and the definition
@zelding Your points are valid; I realize the extract is no good means for examples.
May I give it a second try – with the vars named according to the Slim User guide ‘vocabulary’ and source code. Also I felt it is necessary to not force a user to use a route name. I personally like them a lot and have my routes in a YAML map, but others may have their routes in a DB.
Route data $route_data requires these keys:
Optional keys in $route_data:
class App
{
/**
* Most generic route: Just GET, no middleware stuff.
*/
public $default_route_data = array(
"name" => null,
"methods" => [ "GET" ],
"middleware" => [ ]
);
/**
* @param array $route_data
* @param string $route_name Optional: custom route name
* @return RouteInterface
*/
public function route( array $route_data, string $route_name = null )
{
// Enable user omitting defaults
$route_data = array_merge($this->default_route_data, $route_data);
// Create route instance
$route = $this->map(
$route_data['methods'],
$route_data['pattern'],
$route_data['callable']
);
// Name it (parameter name overrides route data)
$route_name = $route_name ?: $route_data['name'];
if ($route_name):
$route->setName($route_name);
endif;
// Add route middleware
foreach( $middleware as $mw_callable ):
$route->add($mw_callable);
endforeach;
return $route;
}
}
The _route_ method is just a per-route wrapper around ‘eat this, then call map method’. It creates one route as do _get_, _map_ and their friends. IMHO by itself it does not need further validation, as anything thrown in _map_ (and later) will bubble.
zelding's RouteDefinition idea: Why not, a _RouteDefinition_ class can help dealing with route defaults, shortening the method logic. On the other hand, it also would add complexity elsewhere since the instances have to be created somehow after YAML or DB retrieval. Anyhow, the _route_ method could then accept both array or _RouteDefinition_. – Standardization is good, _PSR-66 Routes_ perhaps ;-).
--
Edit: Removed surfluous "->app" in example.
Looking forward for PSR-66 :D
We should not add something like this. It is again some array magic which we have to communicate how this is working, we have to validate the array to give descriptive errors.
Also it is just fine to call $app->map(…)->setName($name)->add($mw)->add($mw2).
Something like managing routes per config should either be an additional module or directly application logic.
I agree with @danopz. This is an application-level thing where people who want it can extend App.
Most helpful comment
We should not add something like this. It is again some array magic which we have to communicate how this is working, we have to validate the array to give descriptive errors.
Also it is just fine to call
$app->map(…)->setName($name)->add($mw)->add($mw2).Something like managing routes per config should either be an additional module or directly application logic.