跳至主要内容

Laravel 框架详解(附 Yii 对照)

Laravel 框架详解(附 Yii 对照)

本文以 Laravel 为主线,系统介绍其基本用法;Yii(以主流的 Yii 2 分支为准)仅在后文以对照方式说明与 Laravel 的差异,不再单独展开完整介绍。内容主要参考 Laravel 官方文档(laravel.com/docs/12.x)与 Yii 官方文档(yiiframework.com/doc/guide/2.0、release-cycle 页面)整理而成。

目录

  1. Laravel 概览
  2. 安装与环境要求
  3. 目录结构
  4. 路由(Routing)
  5. 控制器(Controller)
  6. 数据库与 ORM:Eloquent
  7. 视图与模板引擎:Blade
  8. 表单验证
  9. 命令行工具:Artisan
  10. 认证与权限控制
  11. 生态与工具链
  12. Yii 对照:与 Laravel 的主要差异
  13. 核心区别对比表
  14. 如何选择
  15. 参考资料

1. Laravel 概览

Laravel 由 Taylor Otwell 于 2011 年创建,定位是"优雅、富有表达力的语法",目标是把日常 Web 开发中重复、繁琐的工作(路由、鉴权、缓存、队列、会话等)封装为简洁一致的 API。它是目前 PHP 生态中最流行、社区最庞大的全栈框架,背后由商业公司 Laravel LLC 持续投入,围绕核心框架形成了一整套官方付费/开源工具链:Forge(服务器管理)、Vapor(Serverless 部署)、Nova(后台管理面板)、Envoyer(零停机部署)、以及 Livewire、Inertia.js、Cashier、Horizon、Octane 等专项扩展包。

当前主线版本为 Laravel 12(2025 年发布),最低要求 PHP 8.2。框架遵循 MVC 架构,基于 Composer 管理依赖,内置服务容器(IoC Container)、数据库迁移、队列、事件系统等,使用 MIT 许可证开源。


2. 安装与环境要求

# 使用 Composer 创建项目
composer create-project laravel/laravel example-app

# 或使用官方安装器(需先全局安装 laravel/installer)
laravel new example-app

cd example-app
php artisan serve   # 启动本地开发服务器,默认 http://127.0.0.1:8000

环境要求:PHP 8.2 及以上,并需要常见扩展(Ctype、cURL、DOM、Fileinfo、Filter、Hash、Mbstring、OpenSSL、PCRE、PDO、Session、Tokenizer、XML)。生产环境通常搭配 Nginx/Apache + PHP-FPM,或直接使用 Laravel Sail(Docker 化的本地开发环境)。


3. 目录结构

app/            应用核心代码(Models、Http/Controllers、Providers 等)
bootstrap/      框架启动脚本与缓存
config/         配置文件(每个文件对应一个配置命名空间,如 database.php、cache.php)
database/       迁移(migrations)、数据填充(seeders)、模型工厂(factories)
public/         唯一对外暴露的入口目录(index.php、静态资源)
resources/      视图(Blade)、前端源码(CSS/JS)、语言文件
routes/         路由定义文件(web.php、api.php、console.php)
storage/        日志、缓存、上传文件、已编译的视图
tests/          PHPUnit / Pest 测试用例

设计思路是"约定优于配置":只要按目录约定放置文件,框架就能自动发现(如 app/Models 下的模型、database/migrations 下的迁移文件),减少手动注册的工作量。


4. 路由(Routing)

路由在 routes/web.phproutes/api.php 中以代码方式显式声明,支持闭包或控制器方法,语法直观,可以直接看到项目中所有 URL 的入口。

// routes/web.php
use App\Http\Controllers\PostController;

Route::get('/posts', [PostController::class, 'index']);
Route::get('/posts/{post}', [PostController::class, 'show']); // {post} 自动绑定为模型实例
Route::post('/posts', [PostController::class, 'store'])->middleware('auth');

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

路由还支持路由组(分组添加前缀、中间件)、命名路由(->name('posts.show'),配合 route() 辅助函数生成 URL)、以及速率限制等。


5. 控制器(Controller)

// app/Http/Controllers/PostController.php
class PostController extends Controller
{
    public function index()
    {
        $posts = Post::latest()->paginate(10);
        return view('posts.index', compact('posts'));
    }

    // 路由模型绑定:Laravel 自动根据 URL 中的 {post} 查询对应记录,查不到自动返回 404
    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }
}

控制器方法命名完全自由(不像某些框架要求固定前缀),只受路由文件中映射关系约束。复杂的输入校验逻辑通常抽取为独立的 FormRequest 类,保持控制器方法简洁。


6. 数据库与 ORM:Eloquent

Eloquent 是 Laravel 内置的 ActiveRecord 风格 ORM,模型即数据表的映射,实例即一行数据,查询构造器语法非常流畅、接近自然语言。

// app/Models/Post.php
class Post extends Model
{
    protected $fillable = ['title', 'body'];

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

$posts = Post::where('published', true)
    ->with('comments')          // 预加载关联,避免 N+1 查询
    ->orderBy('created_at', 'desc')
    ->get();

Post::create(['title' => 'Hello', 'body' => '...']);

迁移(Migration)用于以代码方式管理数据库结构变更,可版本化、可回滚:

php artisan make:migration create_posts_table
php artisan migrate
php artisan migrate:rollback

7. 视图与模板引擎:Blade

Blade 是 Laravel 专属的模板引擎,最终会被编译为原生 PHP 并缓存,运行时性能开销很小;提供 @if@foreach@extends/@section(模板继承)等指令,输出默认自动做 XSS 转义。

{{-- resources/views/posts/index.blade.php --}}
@extends('layouts.app')

@section('content')
    <h1>文章列表</h1>
    @foreach ($posts as $post)
        <h2>{{ $post->title }}</h2>
    @endforeach
@endsection

8. 表单验证

既可以在控制器中直接调用 $request->validate(),也可以抽成独立的 FormRequest 类,把校验规则与授权逻辑集中管理,与模型本身解耦。

$validated = $request->validate([
    'title' => 'required|max:255',
    'body'  => 'required',
]);
// app/Http/Requests/StorePostRequest.php
class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return ['title' => 'required|max:255', 'body' => 'required'];
    }
}

9. 命令行工具:Artisan

php artisan 是 Laravel 的命令行瑞士军刀,涵盖代码生成、数据库操作、队列管理、交互调试等。

php artisan make:model Post -mcr   # 同时生成 Model + Migration + Controller(resource)
php artisan make:controller PostController
php artisan tinker                 # 交互式 REPL,可直接操作 Eloquent 模型
php artisan queue:work
php artisan list                   # 查看所有可用命令

make:* 系列命令生成的是"骨架/存根代码"(stub),之后仍需手动补充业务逻辑。


10. 认证与权限控制

核心框架自带基础的 Auth 门面和守卫(Guard)机制,但完整的登录/注册界面脚手架需要额外安装官方生态包:

  • Laravel Breeze / Jetstream:面向传统 Web 应用的登录、注册、邮箱验证等界面。
  • Sanctum:轻量级的 API Token 认证,适合 SPA 或移动端。
  • Passport:完整的 OAuth2 服务器实现。

角色权限(RBAC)本身不是核心内置功能,社区通常使用第三方包(如 spatie/laravel-permission)来实现角色与权限管理。这体现了 Laravel"核心精简、按需通过官方或社区包组合功能"的设计哲学。


11. 生态与工具链

Laravel 的核心竞争力之一是围绕它形成的庞大生态:

  • 部署/运维:Forge(服务器管理)、Vapor(Serverless)、Envoyer(零停机部署)
  • 前端集成:Livewire(服务端渲染的响应式组件)、Inertia.js(连接 Vue/React 而无需单独写 API)
  • 队列与实时:内置队列系统(驱动包括 Redis、数据库、SQS、Beanstalkd),Horizon 提供队列监控面板,Reverb 提供 WebSocket 实时通信
  • 性能:Octane 可将应用常驻内存运行(基于 Swoole/RoadRunner),大幅提升吞吐
  • 测试:PHPUnit 或 Pest 深度集成,Dusk 提供浏览器端到端测试
  • 学习资源:官方文档详尽,配套的 Laracasts 视频教程业界知名,社区规模在 PHP 框架中首屈一指

12. Yii 对照:与 Laravel 的主要差异

Yii(发音类似"忆")由薛强(Qiang Xue)于 2008 年发布,2014 年推出重写后的 Yii 2,是一个强调"高性能、组件化、约定优于配置"的 MVC 框架,最低要求 PHP 7.3(推荐 PHP 8),使用 BSD 许可证;官方也在推进模块化的 Yii 3(独立的 yiisoft/* 包),已有稳定版本,但目前生产环境和文档资源仍以 Yii 2 为主流。以下逐项对照上文各节,说明 Yii 2 的对应做法:

  • 安装:与 Laravel 类似使用 Composer,但官方提供两套"应用模板"——yii2-app-basic(对应中小项目)和 yii2-app-advanced(对应前后台分离的团队项目),而不是像 Laravel 那样只有一套默认骨架。

    composer create-project yiisoft/yii2-app-basic basic
    php yii serve
  • 目录结构:思路相似,也有唯一对外入口目录(web/ 对应 Laravel 的 public/),但配置更集中——config/web.php 以数组形式声明几乎所有"组件"(数据库、URL 管理器、用户会话等),不像 Laravel 把配置拆分到 config/ 下多个独立文件中那样细分。

  • 路由:Laravel 需要在路由文件中逐条显式声明;Yii 默认是约定路由——URL /post/index 直接映射到 PostController::actionIndex(),无需额外声明,只有需要美化 URL 或自定义规则时才在 urlManager 组件里配置规则表。换句话说,Laravel 路由更灵活但需要维护路由文件,Yii 路由更省代码但依赖命名约定。

  • 控制器:Yii 的控制器方法必须以 action 为前缀命名(如 actionIndexactionView($id)),这是约定路由生效的基础;Laravel 的方法名不受此限制。Laravel 特有的"路由模型绑定"(方法参数直接注入模型实例)在 Yii 中没有对应的自动化机制,通常需要手动 findModel($id)

  • ORM:Yii 2 的 ActiveRecord 与 Eloquent 概念一致(模型映射数据表),API 风格也是链式调用,但一个明显区别是:验证规则写在模型的 rules() 方法里,模型自身同时承担"数据库映射"与"数据校验"两个职责,而不像 Laravel 那样倾向把校验单独放进 FormRequest

    class Post extends \yii\db\ActiveRecord
    {
        public function rules() { return [[['title', 'body'], 'required']]; }
    }
    $posts = Post::find()->where(['published' => 1])->with('comments')->all();
  • 视图/模板:Yii 默认不使用独立模板语法,视图文件就是普通 .php 文件,直接混写 HTML 与 PHP(可通过扩展接入 Twig/Smarty);这与 Blade"专属编译型模板引擎、{{ }} 自动转义"的思路不同,Yii 中需要手动调用 Html::encode() 做 XSS 转义。

  • 表单验证:与 ORM 一节呼应,Yii 的校验规则来自模型 rules(),配合 ActiveForm 组件能够自动生成带客户端 + AJAX 双重校验的表单 HTML,前端联动几乎零额外代码;Laravel 的验证更独立、更容易与 Vue/React 等前端框架解耦使用,但没有 Yii 这种"表单自动联动"的开箱体验。

  • 命令行与代码生成:Yii 也有类似 Artisan 的控制台命令(yii migrateyii help 等),但更有特色的是 Gii——一个基于浏览器的可视化代码生成器,可以直接在网页界面勾选数据表、字段,一键生成完整的 Model + CRUD 控制器 + 视图,这是 Laravel 的纯命令行 make:* 所不具备的图形化体验。

  • 认证与权限:这是两者理念差异最明显的一点。Laravel 核心不内置 RBAC,需要额外包(如 spatie/permission);Yii 2 核心直接内置完整的 RBAC 系统yii\rbac\DbManager/PhpManager),可以直接定义角色、权限、规则并做层级继承,开箱即用。

    $auth = Yii::$app->authManager;
    $author = $auth->createRole('author');
    $auth->add($author);
    $auth->assign($author, $userId);
    if (Yii::$app->user->can('author')) { /* 有权限 */ }
  • 生态:Yii 的官方周边生态远小于 Laravel,没有对标 Forge/Vapor/Nova/Livewire 的官方商业工具链,第三方扩展以 yii2-* 命名的 Composer 包为主;学习资源(教程、视频)也明显少于 Laravel。但其核心框架本身"开箱即用的功能密度"(RBAC、Gii、REST 控制器基类等)更高,不完全依赖生态补齐。


13. 核心区别对比表

维度 Laravel Yii 2
首次发布 / 主导者 2011 年,Taylor Otwell(Laravel LLC 商业支持) 2008 年(1.0)/ 2014 年(2.0),薛强与社区维护
最新主线版本 Laravel 12(PHP 8.2+) Yii 2.0.5x 系列(PHP 7.3+);Yii 3 模块化包已有稳定版本
路由方式 显式声明(路由文件 + 闭包/控制器) 约定路由(controller/action)为主,复杂场景配置 URL 规则
ORM Eloquent,查询语法流畅 ActiveRecord,验证规则内置于模型 rules()
模板引擎 Blade(专属语法,编译为 PHP,自动转义) 默认原生 PHP 视图(可选 Twig/Smarty 扩展)
表单处理 Request 验证 / FormRequest,与前端解耦更彻底 ActiveForm + 模型规则,自带客户端联动校验
代码生成 Artisan 命令行(make:* 命令行 + Gii(浏览器可视化 CRUD 生成器)
权限系统 不内置 RBAC,常用第三方包 内置完整 RBAC
API 支持 需 Sanctum/Passport 等包实现 Token 认证 核心自带 yii\rest\Controller,相对开箱即用
官方周边生态 非常庞大:Forge、Vapor、Nova、Horizon、Octane、Livewire、Inertia 等 相对精简,以 yii2-* 扩展包为主
学习资源 极其丰富,Laracasts + 庞大社区 官方文档完善,教程/视频资源少于 Laravel
整体风格 表达力强、约定较松散、生态驱动 显式、组件化、核心功能密度更高

14. 如何选择

  • 需要最快的开发速度、丰富的官方工具链、庞大的社区教程和招聘市场,Laravel 通常是更稳妥的默认选择,也是目前 PHP 生态事实上的主流框架。
  • 项目需要开箱即用的细粒度权限系统(RBAC)、偏好"约定路由 + 集中配置"、或希望借助 Gii 快速搭建管理后台原型,Yii 2 仍是成熟、稳定、性能扎实的选择。
  • 两者核心概念(MVC、ActiveRecord、迁移、依赖注入容器、中间件/过滤器)高度相通,熟悉一个框架后迁移到另一个的学习曲线并不陡峭。

15. 参考资料

此博客中的热门博文

Elasticsearch 读写原理指南

### 1. 什么是 segment,里面装了什么? 在 Lucene(也是 Elasticsearch)里,索引被切分成若干 **segment(段)**,每个 segment 是一个完整的、只读的倒排索引单元。一个 segment 包含: * **倒排词典** —— 用 **FST(Finite‑State Transducer)** 以高度压缩的形式保存每个字段出现的所有 term 以及 term→ord 的映射。对应的磁盘文件是 `*.tim`(新版)或 `*.tis/*.tii`(旧版)。 * **倒排列表(postings)** —— 保存每个 term 出现的文档 ID、频次、位置信息等,文件名通常是 `*.doc`、`*.pos`、`*.pay`。 * **存储字段**(_source、store:true 的字段)—— 以二进制块的形式写入 `*.fdt` / `*.fdx`。 * **doc‑values、norms、向量** 等辅助结构,分别保存在 `*.dv`、`*.norm`、`*.tv` 等文件里。 * **deleted‑docs bitmap**(`*.del`),标记哪些文档已被删除或被更新。 所有这些文件在 segment **写入磁盘后即成为只读**,后续的查询只能读取,永远不会在原文件上进行增删改。 --- ### 2. 原始文档和 FST 为什么都在 segment 里? * **原始文档**:Elasticsearch 默认把完整的 JSON(_source)以及任何 `store:true` 的字段写入 segment 的 `*.fdt/*.fdx` 文件。每个 segment 保存自己的那部分文档,旧的 segment 在合并前仍然保留,直到合并后被删除。 * **FST**:每个字段的词典在每个 segment 中单独维护,采用 FST 进行前缀共享和字节压缩。这样即使同一个 term 在多个 segment 中出现,也会在每个 segment 里拥有独立的映射,查询时只需要在对应 segment 的 FST 中定位即可。 --- ### 3. 查询时到底是怎么遍历 segment 的? 1. **请求入口**      客户端的搜索请求先到达 **协调节点**,协调节点把请求 ...

LLM缓存详解

 可以把“大模型缓存”理解成: 把已经算过的结果(或中间结果)存下来,下次尽量复用 。但这里面其实分几层,不只是简单的“问题→答案”缓存。 1️⃣ 常见的几种缓存类型 (1)KV Cache(推理内部缓存) Transformer 在生成时,会把前面 token 的 Key/Value 向量 缓存下来。 本质:避免重复计算 attention 作用: 同一请求内部加速 特点: 👉 只对“同一上下文继续生成”有效 👉 不跨用户、不跨请求 这类缓存是你体感“流式输出越来越快”的原因之一。 (2)Prompt Cache(提示词缓存) 缓存的是: 相同(或高度相似)的 prompt → 对应的中间表示 / 输出 典型场景: 系统提示词(system prompt)很长 多轮对话里前文基本不变 👉 这里能省掉 前缀计算成本(prefill) (3)Embedding / 语义缓存(Semantic Cache) 这个才是你问题的关键 👇 不是按“字符串完全一致”,而是: 把问题转成向量 → 找“语义相似”的历史问题 → 直接复用答案 2️⃣ 为什么命中缓存成本低很多? 因为大模型推理成本主要在两块: (1)Prefill(吃 prompt) 复杂度 ~ O(n²) 很贵(尤其长 prompt) (2)Decode(逐 token 生成) 每个 token 都要算一遍模型 而缓存命中后: KV cache:不用重复 attention Prompt cache:不用重新 encode 语义缓存: 直接跳过模型推理 👉 相当于从: 几十~几百毫秒 + GPU算力 变成: 一次向量检索(毫秒级)+ 直接返回 所以成本差一个数量级是正常的。 3️⃣ “每个人问法不同,怎么命中缓存?” 这是核心难点,也是工程重点👇 ❌ 不能靠字符串匹配 比如: “今天天气怎么样” “今天外面热不热” 字符串完全不同 → 必须 miss ✅ 用语义相似度(Embedding) 流程一般是: 把问题转 embedding(向量) 在向量数据库里找 TopK 相似问题 如果相似度 > 阈值(比如 0.9) 直接返回缓存答案 一个简单示意 Q1: 北京天气怎么样 → embedding A Q2: 北京今天热吗 → embedding B cosine(A, B) ≈ 0.95...

事务的ACID是什么

 事务的 ACID 是数据库事务必须满足的四个基本性质,用来保证在并发和故障情况下数据的正确性与可靠性: A(Atomicity,原子性) 一个事务中的操作要么 全部成功 ,要么 全部失败回滚 ,不存在“只做了一半”的中间状态。 C(Consistency,一致性) 事务执行前后,数据库都必须处于 一致的合法状态 ,满足约束(如主键、外键、唯一性、业务规则等)。 I(Isolation,隔离性) 并发执行的多个事务之间 相互隔离 ,一个事务未提交的中间结果对其他事务不可见(具体强弱由隔离级别决定)。 D(Durability,持久性) 一旦事务提交成功,其结果会被 永久保存 ,即使系统崩溃也不会丢失(通常依赖 WAL/redo log 等机制)。 一句话记忆: 要么全做完、前后不破坏规则、互不干扰、做完不丢。