Consolidate Resource Controllers with Flexible Filters

📖 1 minute read

Instead of creating separate controllers for nested resources (like PostCommentController, UserCommentController), build one controller with flexible filtering using Spatie Query Builder.

Before: Multiple Controllers

// app/Http/Controllers/PostCommentController.php
public function index(Post $post)
{
    return CommentResource::collection(
        $post->comments()->paginate()
    );
}

// app/Http/Controllers/UserCommentController.php
public function index(User $user)
{
    return CommentResource::collection(
        $user->comments()->paginate()
    );
}

After: Single Controller with Filters

// app/Http/Controllers/CommentController.php
public function index(Request $request)
{
    $query = QueryBuilder::for(Comment::query())
        ->allowedFilters([
            AllowedFilter::callback('post_id', 
                fn ($q, $value) => $q->where('post_id', $value)
            ),
            AllowedFilter::callback('user_id', 
                fn ($q, $value) => $q->where('user_id', $value)
            ),
            AllowedFilter::exact('status'),
        ])
        ->defaultSort('-created_at');

    return CommentResource::collection($query->jsonPaginate());
}

Usage

# Get comments for a post
GET /api/comments?filter[post_id]=123

# Get comments by a user
GET /api/comments?filter[user_id]=456

# Combine filters
GET /api/comments?filter[post_id]=123&filter[status]=approved

Benefits

  • Single source of truth for filtering logic
  • Easier to maintain and test
  • More flexible API for consumers
  • Reduces route bloat

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *