Laravel Web and API: Same or Separate Controllers?

Sometimes you may encounter the situation that you need to return the same data on the web and via API. Should it be in the same or separate controllers? There are a few ways to handle it.

Option 1. Same Controller with Parameter

app/Http/Controllers/UserController.php:

class UserController extends Controller {
public function index($format = 'view') {
$users = User::all();
 
if ($format == 'view') {
return view('users.index', compact('users'));
} else {
return response()->json($users); // or use API Resource here
}
}
}

Option 2. Same Controller with Header

The Controller may define what to return based on the Header of the request. Your front-end client may pass the request with Accept: application/json, for example. Then, you can do:

app/Http/Controllers/UserController.php:

use Illuminate\Http\Request;
 
class UserController extends Controller {
public function index(Request $request) {
$users = User::all();
 
if ($request->expectsJson()) {
return response()->json($users);
} else {
return view('users.index', compact('users'));
}
}
}

Option 3. Separate Controllers

Mixing WEB and API Controllers may be a bad practice, because it goes against the "Separation of Concerns" principle: they serve different purposes so should be separated.

app/Http/Controllers/UserController.php:

class UserController extends Controller {
public function index() {
$users = User::all();
return view('users.index', compact('users'));
}
}

routes/web.php:

use App\Http\Controllers\UserController;
 
Route::get('users', [UserController::class, 'index']);

app/Http/Controllers/Api/UserController.php:

class UserController extends Controller {
public function index() {
$users = User::all();
return response()->json($users);
}
}

routes/api.php:

use App\Http\Controllers\Api\UserController;
 
Route::get('users', [UserController::class, 'index']);

Then the web page can be accessed with /users, and API endpoint can be called with /api/users, as all the routes in routes/api.php file get the "api" prefix automatically.

No comments or questions yet...

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 58 courses (1056 lessons, total 44 h 09 min)
  • 78 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials