'How to override Backpack's UserCrudController?

I am trying to override/extend Backpack's default UserCrudController in Laravel 8 so that I can replace the list and edit operations with my own. To do this I tried:

php artisan backpack:crud User

However, code from the new file in app/Http/Controllers/Admin/UserCrudController.php is not being run, apart from for the 'show' route - presumably because use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation; does not exist in /vendor/backpack/permissionmanager/src/app/Http/Controllers/UserCrudController.php whereas it does in my new controller.

php artisan route:list | grep -i user tells me the following:

|        | GET|HEAD | api/user                |                                    | Closure                                                                                 | api                                                                             |
|        | POST     | user                    | user.store                         | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@store                | web                                                                             |
|        | GET|HEAD | user                    | user.index                         | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@index                | web                                                                             |
|        | GET|HEAD | user/create             | user.create                        | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@create               | web                                                                             |
|        | POST     | user/search             | user.search                        | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@search               | web                                                                             |
|        | PUT      | user/{id}               | user.update                        | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@update               | web                                                                             |
|        | DELETE   | user/{id}               | user.destroy                       | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@destroy              | web                                                                             |
|        | GET|HEAD | user/{id}/details       | user.showDetailsRow                | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@showDetailsRow       | web                                                                             |
|        | GET|HEAD | user/{id}/edit          | user.edit                          | Backpack\PermissionManager\app\Http\Controllers\UserCrudController@edit                 | web                                                                             |
|        | GET|HEAD | user/{id}/show          | user.show                          | App\Http\Controllers\Admin\UserCrudController@show                                      | web                                                                             |

How can I make it so that my new controller takes precedence? My routes/backpack/custom.php currently reads as follows:

Route::group([
    'prefix'     => config('backpack.base.route_prefix', 'admin'),
    'middleware' => array_merge(
        (array) config('backpack.base.web_middleware', 'web'),
        (array) config('backpack.base.middleware_key', 'admin')
    ),
    'namespace'  => 'App\Http\Controllers\Admin',
], function () {
    // custom admin routes
    Route::crud('user', 'UserCrudController');
}); // this should be the absolute last line of this file


Solution 1:[1]

I know I'm late to the game but I'd like to offer a different way to use a custom User CRUD controller. I didn't have to add or change any routes. Just add one line to the app/Providers/AppServiceProvider, under the register() method.

    public function register() {
      //Bind original crud controller to a custom controller
      $this->app->bind(\Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class, \App\Http\Controllers\Admin\UserCrudController::class);

      // ...
    }

Not sure if this is a better or worse way (?). It just make it so I don't have to change any Backpack routes or other code that points to the UserCrudController. Plus, I have all my overrides in one place so I don't have to go hunting in different files.

Not sure it's better, just different.

Solution 2:[2]

Solved this by adding my route to routes/web.php instead of routes/backpack/custom.php, which makes this load in before the permissions package and so take precedence. The code I added was adapted from that in custom.php:

<?php
Route::group([
    'prefix'     => config('backpack.base.route_prefix', 'admin'),
    'namespace'  => 'App\Http\Controllers\Admin',
], function () {
    // routes to override others from Backpack
    Route::crud('user', 'UserCrudController');
});

Solution 3:[3]

I do not see a mistake in your code. Maybe it is due to the order in which the routes are loaded. Basically I did the same as you did, but I put the crud routes in routes/backpack/permissionmanager.php

Edit:

don't know about the order exactly, but the web.php from your laravel project should override all package routes. I expect the order between packages to be "first in, first out", or better "last in, last out". So the package that was loaded last should override the routes of the previous ones.

Since you have defined the routes in routes/backpack/custom.php, I would assume that these routes belong to the backpack base package. Since composer loaded the "backpack base" package before the permissionmanager package, I expect the routes from the permissionmanager to overload these from the "backpack base" package. If routes from different packages interact with each other, imho the package that came last should be in charge.

Solution 4:[4]

Just simply create routes/backpack/permissionmanager.php file with this script

<?php

/*
|--------------------------------------------------------------------------
| Backpack\PermissionManager Routes
|--------------------------------------------------------------------------
|
| This file is where you may define all of the routes that are
| handled by the Backpack\PermissionManager package.
|
*/

Route::group([
    'namespace'  => 'Backpack\PermissionManager\app\Http\Controllers',
    'prefix'     => config('backpack.base.route_prefix', 'admin'),
    'middleware' => ['web', backpack_middleware()],
], function () {
    Route::crud('permission', 'PermissionCrudController');
    Route::crud('role', 'RoleCrudController');
    // Route::crud('user', 'UserCrudController');
});

Route::group([
    'namespace'  => 'App\Http\Controllers\Admin',
    'prefix'     => config('backpack.base.route_prefix', 'admin'),
    'middleware' => ['web', backpack_middleware()],
], function () {
    // Route::crud('permission', 'PermissionCrudController');
    // Route::crud('role', 'RoleCrudController');
    Route::crud('user', 'UserCrudController');
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Xaratas
Solution 2 Tristan Roddis
Solution 3
Solution 4 Gerry Ahmadi