目录结构
Laravel 的默认应用结构对大小应用都是个好起点。但你完全可以按自己喜欢的方式组织——Laravel 几乎不限制类的存放位置,只要 Composer 能自动加载(autoload)这个类就行。
根目录
app 目录
app 目录装着你应用的核心代码。我们一会儿会细讲这个目录;总之,你应用里几乎所有的类都在这。
bootstrap 目录
bootstrap 目录里有 app.php 文件,框架的启动就在这进行。这个目录还有个 cache 子目录,放框架为提速生成的缓存文件(比如路由缓存、服务缓存)。
config 目录
config 目录,顾名思义,放应用的所有配置文件。建议你把这些文件都翻一遍,熟悉有哪些可调项。
database 目录
database 目录放数据库迁移(Migration)、模型工厂(model factory)和种子(seed)。如果你想,也可以把 SQLite 数据库文件放这。
public 目录
public 目录里有 index.php——所有进入你应用的请求都从这个文件进来,它也配置了自动加载。这个目录还放你的静态资源(assets),比如图片、JavaScript、CSS。
术语:public 是应用前门
public/ 是应用的"前门"——只有这个目录该被外部访问到,index.php 是所有请求的入口;public/ 之外的文件(.env 有密码、config/ 有配置、app/ 有业务代码)都不该被外面读到。所以部署时 Web 服务器的对外起点必须对到 public/,别对到项目根,否则敏感文件会泄露、CSS/路由也会乱。
resources 目录
resources 目录放你的视图,以及原始、未编译的资源(CSS 或 JavaScript)。
routes 目录
routes 目录放应用的所有路由定义。Laravel 默认带两个路由文件:web.php 和 console.php。
web.php 里的路由会被 Laravel 放进 web 中间件组,自带会话状态、CSRF 防护、cookie 加密。如果你的应用不是无状态的 RESTful API,那绝大多数路由都会定义在 web.php 里。
术语:中间件和 CSRF
**中间件(Middleware)**是请求处理链上的过滤层——请求进来和响应出去之间做点事,比如认证、日志、CORS。web 中间件组就是给"有页面的"路由准备的一套常用中间件。CSRF(跨站请求伪造)是攻击者借用户的登录态在别的站点偷偷发请求的套路;web 组自动给表单加 CSRF token 防这个。
console.php 用来定义所有基于闭包的控制台命令。每个闭包绑定到一个命令实例上,方便和命令的 IO 方法交互。虽然这个文件不定义 HTTP 路由,但它定义的是控制台进入你应用的入口(也算一种"路由")。你也可以在 console.php 里调度任务。
举个例子,在 routes/console.php 里写:
use Illuminate\Support\Facades\Artisan;
Artisan::command('mail:send {user}', function ($user) {
$this->info("给用户 {$user} 发邮件");
})->purpose('给指定用户发邮件');
然后终端跑 php artisan mail:send 1 就执行了这个闭包。{user} 是命令参数,闭包的 $user 按参数名接它的值;$this 是命令实例,能用 info()、error() 等方法输出。这比 make:command 生成完整命令类轻量,适合简单的一次性任务;逻辑复杂还是用命令类。
可选地,你可以通过 install:api 和 install:broadcasting Artisan 命令装上额外的路由文件:API 路由(api.php)和广播频道(channels.php)。
api.php 里的路由设计为无状态,所以从这些路由进来的请求靠令牌认证,访问不到会话状态。
channels.php 用来注册你应用支持的所有事件广播频道。
storage 目录
storage 目录放日志、编译后的 Blade 模板、基于文件的会话、文件缓存,以及框架生成的其它文件。这个目录分成 app、framework、logs 三个子目录:app 放你应用生成的文件;framework 放框架生成的文件和缓存;logs 放应用的日志文件。
storage/app/public 用来存用户产生的、需要公开访问的文件,比如用户头像。你应该在 public/storage 建一个指向这个目录的符号链接(软链),用 php artisan storage:link 命令建。
常见坑:忘了 storage:link,用户上传的文件 404
用户上传的文件默认存到 storage/app/public/,但只有 public/ 是对外可访问的,所以得用 storage:link 在 public/storage 建一个软链指向 storage/app/public。没建这个软链,上传的文件 URL 会 404。新项目部署后记得先跑一次 php artisan storage:link。
tests 目录
tests 目录放你的自动化测试。Laravel 自带 Pest 或 PHPUnit 的单元测试和功能测试示例。每个测试类名要以 Test 结尾。跑测试用 /vendor/bin/pest 或 /vendor/bin/phpunit;想看更详细、更好看的结果,用 php artisan test 命令。
vendor 目录
vendor 目录放你的 Composer 依赖。
app 目录
你应用的绝大部分代码都在 app 目录。默认这个目录的命名空间是 App,由 Composer 按 PSR-4 自动加载标准自动加载。
术语:PSR-4 自动加载
PSR-4 是 PHP 标准的"命名空间→文件路径"映射规则:App\Http\Controllers\UserController 这个类,对应的文件就是 app/Http/Controllers/UserController.php。所以你新建类只要放对路径、命名空间写对,Composer 就能自动找到它,不用手动 require。
默认 app 目录里有 Http、Models、Providers 三个子目录。但随着你用 make: 系列 Artisan 命令生成类,会陆续生成其它子目录。比如 app/Console 目录在你跑 make:command 生成命令类之前是不存在的。
Console 和 Http 目录下面会单独讲,你可以把它们理解成"应用核心的入口 API"。HTTP 协议和 CLI 都是跟你应用交互的方式,但它们本身不含业务逻辑——换句话说,它们是给应用下命令的两条通道。Console 目录放你所有的 Artisan 命令,Http 目录放控制器、中间件、请求。
信息
app 目录里很多类都能用 Artisan 命令生成。想看有哪些可用命令,在终端跑 php artisan list make。
Broadcasting 目录
Broadcasting 目录放你应用所有的广播频道类。这些类用 make:channel 命令生成。这个目录默认不存在,你创建第一个频道时会自动建。想了解更多,看事件广播文档。
Console 目录
Console 目录放你应用所有的自定义 Artisan 命令。这些命令用 make:command 生成。
区别:console.php 闭包命令 vs make:command 命令类
两种都能定义 Artisan 命令,最终都注册到 Artisan、php artisan list 都列出,效果一样——只用 make:command 完全够用,不需要 console.php。区别在形式和适用场景:
- console.php 闭包:一个闭包写在
routes/console.php,轻量、适合一次性临时脚本和调度任务入口,难单独测试。 - make:command 命令类:独立类文件在
app/Console/Commands/,自动注册,适合复杂逻辑、要复用/测试的命令。
底层都注册成 Command 子类。简单临时任务用闭包;正经命令用类。
Events 目录
这个目录默认不存在,你跑 event:generate 或 make:event 命令时会自动建。Events 目录放事件类。事件用来通知应用其它部分"某件事发生了",提供很好的灵活性和解耦。
Exceptions 目录
Exceptions 目录放你应用所有的自定义异常(exception)。这些异常用 make:exception 生成。
Http 目录
Http 目录放你的控制器(Controller)、中间件(Middleware)、表单请求(Form Request)。处理进入应用请求的几乎所有逻辑都放在这。
术语:表单请求 Form Request
表单请求是一个专门的请求类,把"这个请求要怎么验证"封装进去——比如 StorePostRequest 里写好 rules() 返回字段校验规则,Laravel 在进控制器之前自动跑验证,不通过就自动返回错误。比在控制器里手写一堆 if 干净。
Jobs 目录
这个目录默认不存在,你跑 make:job 命令时会自动建。Jobs 目录放你应用的队列任务。任务可以丢队列异步跑,也可以在当前请求生命周期里同步跑。同步跑的任务有时叫"命令(command)",因为它们是命令模式的实现。
Listeners 目录
这个目录默认不存在,你跑 event:generate 或 make:listener 命令时会自动建。Listeners 目录放处理你事件的类。事件监听器收到一个事件实例后执行响应逻辑。比如 UserRegistered 事件可以由 SendWelcomeEmail 监听器处理。
Mail 目录
这个目录默认不存在,你跑 make:mail 命令时会自动建。Mail 目录放你应用表示邮件的所有类。邮件对象让你把构建邮件的全部逻辑封装进一个简单的类,用 Mail::send 发送。
Models 目录
Models 目录放你所有的 Eloquent 模型类。Laravel 自带的 Eloquent ORM 提供了一套漂亮、简洁的 ActiveRecord 实现,用来操作数据库。每个数据库表对应一个"模型",你用模型查表里的数据、往表里插新记录。
术语:Eloquent ORM 和 ActiveRecord
ORM(对象关系映射)就是用 PHP 对象操作数据库,不用写 SQL。ActiveRecord 是一种 ORM 风格:一个模型类对应一张表,一个模型实例对应表里一行——比如 User 模型对应 users 表,new User(['name'=>'ab'])->save() 就插一条记录。Laravel 的 Eloquent 就是这种风格。
Notifications 目录
这个目录默认不存在,你跑 make:notification 命令时会自动建。Notifications 目录放你应用发出的所有"事务性"通知,比如应用里发生某件事时发的简单通知。Laravel 的通知功能把"发通知"抽象出来,一套代码可以走邮件、Slack、短信、或存数据库等多种驱动。
Policies 目录
这个目录默认不存在,你跑 make:policy 命令时会自动建。Policies 目录放你应用的授权策略类。策略用来判断某个用户能不能对某个资源做某个动作(比如"这个用户能不能编辑这篇文章")。
Providers 目录
Providers 目录放你应用所有的服务提供者。
术语:服务容器和服务提供者
服务容器是 Laravel 管理依赖的中心——你把"我需要什么"告诉它,它把对应实例给你(依赖注入就靠它)。服务提供者是应用启动时干活的入口:往服务容器里绑定服务、注册事件、做各种"准备好接请求"的初始化。框架启动时会依次跑所有服务提供者的 register() 和 boot()。
新装的 Laravel 应用,这个目录里已经有 AppServiceProvider。你可以按需往这里加自己的服务提供者。
Rules 目录
这个目录默认不存在,你跑 make:rule 命令时会自动建。Rules 目录放你应用的自定义验证规则对象。规则用来把复杂的验证逻辑封装进一个简单对象。更多信息看验证文档。