Laravel同时存在网页端与API时如何配置路由避免控制器重复?
解决方案
最优最高效方案:利用Laravel内置的请求类型判断
Laravel 自带expectsJson()方法,可以自动识别当前请求是否需要返回JSON格式响应,不需要拆分控制器,只需要修改原CustomersController的index方法,加一行判断逻辑即可,全程复用现有查询代码,没有冗余。
代码示例
原index方法逻辑:
public function index() { $customers = Customer::all(); return view('customers.index', compact('customers')); }
修改后的兼容逻辑:
public function index() { $customers = Customer::all(); // 识别API请求自动返回JSON,网页请求照常返回视图 if (request()->expectsJson()) { // 简单场景可直接返回集合,Laravel会自动序列化为JSON // return $customers; // 规范场景推荐用API资源统一格式化输出结构 return \App\Http\Resources\CustomerResource::collection($customers); } return view('customers.index', compact('customers')); }
路由配置
直接在api.php中添加对应路由即可,API路由默认带/api前缀,不会和web路由冲突:
use App\Http\Controllers\CustomersController; Route::get('/customers', [CustomersController::class, 'index']);
进阶优化(适合复杂业务场景)
如果后续客户查询逻辑变复杂(需要加筛选、分页、权限判断等),可以把公共业务逻辑抽成服务层,后续就算要拆分Web和API控制器也不会产生重复代码:
- 新建服务类
app/Services/CustomerService.php封装查询逻辑:
namespace App\Services; use App\Models\Customer; class CustomerService { public function getCustomerList() { return Customer::query() ->where('is_active', 1) ->latest() ->paginate(20); } }
- 控制器中注入服务类调用:
public function index(CustomerService $customerService) { $customers = $customerService->getCustomerList(); if (request()->expectsJson()) { return \App\Http\Resources\CustomerResource::collection($customers); } return view('customers.index', compact('customers')); }
方案优势
- 零额外扩展依赖,完全符合Laravel原生设计规范
- 100%复用现有业务逻辑,没有冗余代码
- 扩展性强,后续修改查询逻辑只需要改动一处即可同步生效到网页端和API端
- 性能无额外损耗,
expectsJson()仅做请求头判断,开销可以忽略
内容的提问来源于stack exchange,提问作者The Stompiest
相关产品推荐
相关产品推荐

