Good Code
The good version makes the route and controller boundary easy to scan: HTTP data is validated elsewhere, the user and input are passed to a service, and the response status is explicit.
Lesson 01
Keep Laravel route files focused on URL wiring and let controllers hand request work to application services.
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreReviewRequest;
use App\Services\ReviewService;
use Illuminate\Http\JsonResponse;
final class ReviewController
{
public function __construct(private ReviewService $reviews) {}
public function store(StoreReviewRequest $request): JsonResponse
{
// Controller maps HTTP input to an application service call.
$review = $this->reviews->create($request->user(), $request->validated());
return response()->json($review, 201);
}
}<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
Route::post('/reviews', function (Request $request) {
// The route closure owns validation, persistence, and response shape.
$data = $request->validate(['title' => 'required', 'body' => 'required']);
$id = DB::table('reviews')->insertGetId([
...$data,
'user_id' => $request->user()->id,
]);
return ['id' => $id, ...$data];
});The good version makes the route and controller boundary easy to scan: HTTP data is validated elsewhere, the user and input are passed to a service, and the response status is explicit.
The bad version puts too much behavior in the route file. A reviewer has to audit validation, database writes, ownership, and response shape in the same closure.