多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE

技术文章

聚焦一线编程技术原理与实战踩坑,沉淀可复用的工程经验。

PHP Laravel 框架路由与中间件详解

PHP Laravel 框架路由与中间件详解

Laravel 是当前最流行的 PHP 框架之一,它的路由与中间件机制是理解整个请求生命周期的钥匙。从请求进入应用、经过中间件过滤、匹配路由、分发到控制器、最终返回响应,这条链路清晰而优雅。本文带你走完这条链路的每一环。

一、路由定义:请求的入口

Laravel 路由定义在 routes/web.php(web 路由)和 routes/api.php(API 路由)。每条路由声明了 HTTP 方法、URI 与处理逻辑。

// routes/web.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;

// 基础闭包路由
Route::get('/', function () {
    return view('welcome');
});

// RESTful 资源路由:一次生成 index/create/store/show/edit/update/destroy
Route::resource('posts', PostController::class);

// 路由分组:共享前缀、中间件、命名空间
Route::prefix('admin')->middleware(['auth', 'admin'])->group(function () {
    Route::get('/dashboard', [AdminController::class, 'dashboard'])->name('admin.dashboard');
    Route::resource('users', UserController::class);
});

路由命名(->name())让你在代码里用 route('admin.dashboard') 生成 URL,URI 变了也不用改引用处。

二、中间件:请求的过滤层

中间件是请求进入控制器前、响应返回浏览器前的"过滤层"。典型用途包括认证、CORS、日志、限流。它形成一条管道,每个中间件都可以在请求前、响应后做处理。

// 生成中间件:php artisan make:middleware CheckAge
// app/Http/Middleware/CheckAge.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckAge
{
    public function handle(Request $request, Closure $next)
    {
        // 请求前置逻辑
        if ($request->age < 18) {
            return response('未成年禁止访问', 403);
        }
        $response = $next($request);  // 传递给下一层
        // 响应后置逻辑
        return $response;
    }
}

心智模型:中间件像洋葱,请求从外向内穿过每一层,响应再从内向外穿出。$next($request) 是"放行"的关键。

注册中间件到 app/Http/Kernel.php,可全局生效,也可作为路由中间件按需挂载:

// 仅给某条路由挂中间件
Route::get('/profile', [UserController::class, 'profile'])
     ->middleware('auth', 'check.age');

三、控制器:业务逻辑的归处

路由闭包适合简单逻辑,复杂业务应放到控制器。Laravel 的控制器支持依赖注入,类型提示的参数会被容器自动解析。

namespace App\Http\Controllers;

use App\Http\Requests\StorePostRequest;
use App\Models\Post;
use App\Services\SlugService;
use Illuminate\Http\Request;

class PostController extends Controller
{
    // 构造函数注入:服务由容器解析
    public function __construct(protected SlugService $slug) {}

    public function store(StorePostRequest $request)
    {
        // Request 注入:表单验证已在 StorePostRequest::rules() 完成
        $data = $request->validated();
        $data['slug'] = $this->slug->generate($data['title']);

        $post = Post::create($data);
        return response()->json($post, 201);
    }
}

四、依赖注入与服务容器

Laravel 的服务容器是依赖注入的核心。绑定接口到实现,解析时自动注入依赖,让代码解耦、易测试。

// 绑定接口到实现
// app/Providers/AppServiceProvider.php
public function register()
{
    $this->app->bind(
        \App\Contracts\PaymentInterface::class,
        \App\Services\AlipayService::class
    );
}

// 使用时类型提示即可,容器自动解析
class OrderController
{
    public function pay(\App\Contracts\PaymentInterface $payment)
    {
        $payment->charge(100);
    }
}

bind 每次解析都返回新实例,singleton 全局共享一个实例。单例适合无状态的连接池、配置类。

五、请求生命周期串讲

把上面几个概念串起来,一个完整请求的流程是:

  • 入口:请求进入 public/index.php,启动应用。
  • 路由匹配:Router 根据 URI+方法找到匹配路由。
  • 中间件管道:依次执行全局中间件、路由中间件。
  • 控制器执行:依赖注入解析参数,调用控制器方法。
  • 响应返回:响应反向穿过中间件管道,返回浏览器。
// 简化的中间件管道示意
$pipeline = array_reduce($middlewares, function ($next, $middleware) {
    return function ($request) use ($middleware, $next) {
        return $middleware->handle($request, $next);
    };
}, $finalHandler);
return $pipeline($request);

六、实战建议

  • 路由分组:按业务模块分组,统一前缀与中间件,避免重复。
  • 中间件职责单一:一个中间件只做一件事(认证、限流、日志分开),便于复用与测试。
  • 用 FormRequest 做校验:把验证规则抽到 Request 类,控制器保持干净。
  • 面向接口编程:依赖接口而非具体类,配合容器绑定,便于替换实现与单元测试。

Laravel 的优雅来自于它对"请求生命周期"的清晰抽象。理解了路由、中间件、控制器、容器这四块如何协作,你就掌握了 Laravel 工程化的骨架,剩下的视图、ORM、队列都是在这套骨架上的能力扩展。

返回列表