How to setup Nested CRUD

Imagine a blog's admin who could list all posts in the admin panel. What if the admin wants to see a list of articles posted by a user...

Karan Datwani
Karan Datwani
Share:

Imagine a blog's admin who could list all posts in the admin panel. What if the admin wants to see a list of articles posted by a user named Mr. X without using filters? He just wants to go from the User CRUD to the list of his posts.

For this case, we can create a nested resource. We'd be creating a third CRUD Controller, UserPostCrudController, which is exactly like your PostCrudController, but it adds a constraint to only show one user's posts.

image

Let's get started

For the above example, we can assume two models are linked to each other:

  • a Post model
  • a User model

And we will have the following admin routes where:

  • admin/post/ - the admin can see all posts;
  • admin/user/ - the admin can see all users;
  • admin/user/{user_id}/post/ - the admin (or someone else) can see a user's posts;

Step 1. Add a button

To go to user posts, I'm adding a button to the user CRUD.

protected function setupListOperation()
    {
        CRUD::column('name');
        ....
        
        CRUD::button('view_posts')->stack('line')->view('crud::buttons.quick')->meta([
            'access'  => true,
            'label'   => 'See Posts',
            'icon'    => 'las la-newspaper',
            'wrapper' => [
                'href' => function ($entry, $crud) {
                    return url($crud->route.'/'.$entry->getKey().'/post');
                },                
            ],
        ]);
    } 

Step 2. Create your new controller

In this new controller, UserPostCrudController, I can extend the PostCrudController and specify what's different about it:

use Illuminate\Database\Eloquent\Builder;

class UserPostCrudController extends PostCrudController
{
    public function setup()
    {
        parent::setup();

        // get the user_id parameter from route and find the user
        $user_id = \Route::current()->parameter('user_id');
        $user = User::findOrFail($user_id);

        // set a route for the above button
        CRUD::setRoute(config('backpack.base.route_prefix') . '/user/' . $user_id . '/post');

        // set title for the CRUD
        CRUD::setEntityNameStrings("$user->name's post", "$user->name's posts");

        // show only that user's blogs
        CRUD::addBaseClause(function (Builder $query) use ($user_id) {
            $query->whereHas('users', function (Builder $query) use ($user_id) {
                $query->where('user_id', $user_id)
                    ->where('role', 'user');
            });
        });
    }
}

Step 3. Add the route

Include the route for UserPostCrudController inside routes/backpack/custom.php:

// Admin Routes
Route::crud('post', 'PostCrudController');
Route::crud('user', 'UserCrudController');

// Route For the User's Posts
Route::group(['prefix' => 'user/{user_id}'], function(){
    Route::crud('post', 'UserPostCrudController');
});

That's it. Your admins should now be able to see users, posts, and user's posts.

Cheers!

Want to receive more articles like this?

Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.

Reactions & Comments

What do you think about this?

Latest Articles

Wondering what our community has been up to?