[译]Laravel 5.0 之目录结构与命名空间

本文译自 Matt Stauffer系列文章.


Laravel 的主版本号之所以从 4 升到 5. 一个很重要的原因是目录结构的改变. 这个改变实际上不只是文件组织方式的变化, 而是思想上的一个重大转变.

新的目录结构能够更好地反映 Laravel 开发者的工作方式或者说推荐的工作方式. 不仅如此, 新的目录结构也能够减少有关 “最佳实践” 这个话题的争论. 此外, 从新的目录结构也能更好地理解 Laravel 的工作机制.

新版本的目录结构

app
    Commands
    Console
    Events
    Handlers
        Commands
        Events
    Http
        Controllers
        Middleware
        Requests
    Providers
    Services
bootstrap
config
database
    migrations
    seeds
public
    package
resources
    lang
    views
storage
    cache
    logs
    meta
    sessions
    views
    work
tests

总的来说, app 目录被精简了, 但作用提升了. 以前它更像是 Rails/CodeIgniter 风格的代码目录, 包含了应用逻辑, 应用配置, 视图模板, 持久化存储等除了静态资源以外的几乎所有东西. 而在新的目录结构下, 它只包括应用逻辑(包括业务领域), 并且遵循 PSR-4 规范来进行类的自动加载.

由此带来的是, Laravel 相关的配置文件保存在了自己的独立目录下, 资源文件–语言和视图–保存在了自己的独立目录下, 数据库相关的信息也保存在了它们自己的目录下.

提示: 有一个遗留的 Service Provider (参见文档) 允许以 4.2 以下的目录结构运行 5.0 版本. 因此把旧版本的 Laravel 应用升级到 5.0 并不强制要求改为新的目录结构.

新的目录结构那些进步?

那么, 5.0 版的新结构到底带来了什么改进呢?

对于 Laravel 框架的初学者来说, 问题被分解了. 在以前的版本中 app 目录几乎涵盖了除前端代码之外的所有内容, 而现在它聚焦于应用的核心逻辑. 确切地说, 是把一些特定的实现细节挪到了别的地方.

除此之外, 把域逻辑放到一个 “App” 风格的顶级命名空间下也是经过了时间检验的最佳实践. 对我们大多数人而言, 创建一个新项目(旧版本的)之后, 至少要花时间去删除 models 目录, 给应用添加命名空间, 按照 PSR-4 规范设置该命名空间的类自动加载. 现在这些工作已经变成了默认目录结构的一部分. 给 Controllers 和其它与框架有关的代码归类到对应命名空间下的工作也因此变得简单多了.

最后,原来写在过程文件(比如 filters)中的代码现在移到了类和 Service Providers 中. 可以减少过程代码, 使执行更容易预测. 同时也鼓励对 Service Providers 的用户态使用(即 “在我们的代码里,而不是在框架代码里”).

It’s a little too extreme to say that the code in your app directory should be framework independent; controllers, filters, commands, and service providers will extend Laravel classes, and all of your classes may inherit from or receive injections of Laravel classes. But, this change goes a long way to moving the primary logic of your applications into PSR-4 loaded classes that could theoretically exist independent of Laravel.

app 目录下的代码完全不耦合于框架的话可能有点极端了. 毕竟 Controllers, filters, commands 和 service providers 都是对 Laravel 框架中的类的扩展, 并且可能你的所有类可能要么接收 Laravel 类的注入, 要么被注入到 Laravel 类. 但 5.0 版本改用 PSR-4 规范来实现主要逻辑的自动加载已经是一大进步, 为把应用代码与 Laravel 进行分离提供了理论上的可能.

xxx 应该放在哪里?

如果 xxx 代表的是某个类, 或者可以写成一个类的话, 它应该放在 app/ 下的某个地方. 如果 xxx 代表的是 Eloquent model, 它应该放在 app/ 下的某个地方. 如果 xxx 要通过 Web 服务器来处理发送给请求流(比如 Controllers 和 FormRequests), 它应该放在 app/Http 目录下. 如果 xxx 要通过 CLI (命令行界面) 来处理请求, 它应该放在 app/Console 目录下. 如果 xxx 在以前的版本中是放在 routes.php 文件中(但它不是一个路由定义), 或者是放在 start.php 文件中, 那么现在它应该写到某个 Service Provider 里. 如果 xxx 是一个过滤器(filter), 它应该放在 app/Http/Filters 目录里一个专属于它的类中.

如果 xxx 不属于上面的任何一种情况, 那么从目录结构就可以很清楚看出它应该放在哪里了.

代码中的命名空间(namespace)是怎么工作的?

默认情况下, 每个 Laravel 应用都有一个代表应用类的顶级命名空间, 一般来说这个命名空间是 “App”, 它对应的着 app/ 目录, 遵循 PSR-4 规范.

但你只要执行一个 artisan 命令, 可以很轻松地修改 “App/” 下所有实例的根命名空间.

比如新建了一个 Laravel 项目之后, 可以马上执行下面的 artisan 命令, 把根命名空间从 “App” 改为 “Confomo”:

$ php artisan app:name Confomo

执行完这个命令之后, app/ 目录下的所有类都被归入 “Confomo” 命名空间下. composer.json 文件里的 PSR-4 自动加载语句会自动更新, Laravel 也清楚应该在哪里去寻找该命名空间下的 filters, controlers 等.

写在最后

Laravel 5.0 中新的应用目录结构和应用命名空间可以帮助我们一步步地提升代码的健壮性, 一致性和代码质量. 我要给它点32个赞.

本文或有遗漏或不足之处, 欢迎通过 Twitter 联系文章原作者 <@stauffermatt>. 或者在下面留下评论, 与译者 kairee 交流.