Nested resources in Backpack CRUD

Posted in Tutorials by Cristian Tabacitu - 29th of November 2016

Sometimes you'll have one resource that depends on another one. For example, you might have:

  • a Post model;
  • a User model;

The admins could see all posts, of course. But if you might want to see only one user's posts. Sometimes, you don't want to be using a filter. You just want to go from a User to that User's posts. In this case, you can create a nested resource. Basically you'd be creating a third admin panel, UserPostCrudController, which is exactly like your PostCrudController, but it adds a constraint to only show one user's posts.

So you'd have the following admin panels (and routes):

  • 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

You'll need to show a button next to the Edit/Delete buttons, to take the admin to the User's posts. You can do that by creating a custom button.

1.1. Create a new blade file in your /resources/views/vendor/backpack/crud/buttons/, named user_posts.blade.php, that looks something like this: <a href="{{ Request::url().'/'.$entry->getKey() }}/post" class="btn btn-xs btn-default"><i class="fa fa-eye"></i> See Posts</a>.

1.2. Now tell your UserCrudController to show that new button we've created: $this->crud->addButtonFromView('line', 'user_posts', 'user_posts', 'beginning');

Step 2. Create your new controller

In this new controller, UserPostCrudController, we could just extend the PostCrudController and specify what's different about it:

<?php namespace App\Http\Controllers\Admin;

use Backpack\CRUD\app\Http\Controllers\CrudController;
use App\Http\Controllers\Admin\PostCrudController;

// VALIDATION: change the requests to match your own file names if you need form validation
use App\Http\Requests\PostRequest as StoreRequest;
use App\Http\Requests\PostRequest as UpdateRequest;

class UserPostCrudController extends PostCrudController {

    public function setup() {
        parent::setup();

        // get the user_id parameter
        $user_id = \Route::current()->parameter('user_id');

        // set a different route for the admin panel buttons
        $this->crud->setRoute("admin/user/".$user_id."/post");

        // show only that user's posts
        $this->crud->addClause('where', 'user_id', $user_id); 
    }

    public function store(StoreRequest $request)
    {
        return parent::storeCrud();
    }

    public function update(UpdateRequest $request)
    {
        return parent::updateCrud();
    }
}

Step 3. Add the route

Your routes file (routes/web.php) should include a third route, that points to this new UserPostCrudController we've created. It might look something like this:

// Admin Interface Routes
Route::group(['prefix' => 'admin', 'middleware' => ['web', 'auth'], 'namespace' => 'Admin'], function()
{
    CRUD::resource('post', 'PostCrudController');
    CRUD::resource('user', 'UserCrudController');

    // !!! DIFFERENT ADMIN PANEL FOR USER POSTS
    Route::group(['prefix' => 'user/{user_id}'], function()
    {
        CRUD::resource('post', 'UserPostCrudController');
    });
});

That's it. Your admins should now be able to see Users, Posts and User's posts.

Cheers!