Skip to content

[4.0][Feature][Proposal] Automatic routes for CrudControllersΒ #1877

@tabacitu

Description

@tabacitu

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 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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions