-
Notifications
You must be signed in to change notification settings - Fork 920
Description
Right now, if you want to add a new Operation (say... moderate), you also have to add the new route for it. For example, in backpack instant fields @tswonke instructs you to do:
CRUD::resource('entity', 'EntityCrudController')->with(function () {
Route::any('entity/ajax/{mode?}', 'EntityCrudController@handleAjaxRequest');
});
Which is a simple way to do it. But I'd rather not go to a different file to enable a CrudController operation. I think use InstantFields;
should be the only step.
This small inconvenience is also present when using select2_from_ajax
fields. You have to create a method, but you also have to create a route for it, in a different file.
Solution 1.
We could expose all public
methods in your EntityCrudController
as routes.
PROs:
- It would also make it dead-simple to create new operations - just create a new public method;
- It would make it super simple to install operations from other packages; just
use TraitName
; - It's similar to how CodeIgniter did it, so it should be familiar to those coming from there;
CONs:
- We have to be very VERY clear that public methods have routes generated for them, so that people don't create
public
methods in EntityCrudControllers willy-nilly; This would probably get solved with a comment inside generated EntityCrudControllers (just split the file into private methods and public methods); - We will need some conventions, to settle the action and parameters for the route; probably:
- the method has to be
public
for it to have a route; - if the method name does not begin with HTTP verb (get, post, put, patch, delete, options), then it'll assume it's
get
; - if the method has parameters (other than a Request), then the route should have the same parameters;
- if the parameters have a default value, they are optional; otherwise they're required;
public function index()
defaults to the main route;- the route name will be the method name;
- the method has to be
The rules above would mean you'd only need Route::allPublicMethodsFrom('ProductCrudController');
in the route file. Then inside the ProductCrudController:
Method definition | Instead of defining route like so |
---|---|
public function moderate() |
Route::get('moderate', 'ProductCrudController@moderate') |
public function postModerate() |
Route::post('moderate', 'ProductCrudController@postModerate') |
Existing methods would become:
Method definition | Instead of defining route like so |
---|---|
public function index() |
Route::get('', 'CrudController@index') |
public function create() |
Route::get('create', 'CrudController@create') |
public function postCreate(StoreRequest $request) |
Route::post('create', 'ProductCrudController@store') |
public function update() |
Route::get('update', 'CrudController@update') |
public function postUpdate() |
Route::post('create', 'ProductCrudController@store') |
Solution 2.
We could have a getRoutes()
method on the CrudController that gets the routes; Developers would be able to customize it:
private function routes() {
$defaultRoutes = parent::routes();
$customRoutes = [
'get' => [
// route definition => 'method name'
'moderate/{id}' => 'moderateee',
],
'post' => [
'moderate/{id}' => 'postModerate',
'moderate/{id}/comment/{comment_id}/edit' => 'editComment',
],
'put' => [
'moderate/{id}/comment' => 'addComment',
],
'patch' => [
],
'delete' => [
'moderate/{id}/comment/{comment_id}/delete' => 'deleteComment',
],
];
return array_merge_recursive($defaultRoutes, $customRoutes);
}
Solution 3.
Instead of making all routes as proposed in Solution 1, we could just add the ability to expose extra routes just by making the method public and including the verb in the name. So edit()
would not have an auto-route. But getEdit
would.
Thoughts, anyone?