Laravel 作为大名鼎鼎的 PHP Web 框架,有着「过度设计」的美誉(滑稽)。也就免不了附带着一些需要学习和摸索才能掌握的奇技淫巧(好吧其实只需要看看文档就行)。笔者结合自身的开发经验,把值得一提的东西梳理成文,便于读者在使用 Laravel 进行开发时事半功倍。
Composer
已经 9102 年了,Composer 作为 PHP 的包管理工具,相信已经不需要做介绍了。使用 Laravel 的过程中不可避免地会使用到各种各样的第三方包,Laravel 毫无疑问是使用 Composer 进行包管理的,对于国内开发者而言,第一件事显然是把 Composer 换为国内源,只需执行一下命令即可修改全局设置:
|
|
调试代码
打印变量
一般使用框架自带的 dd() 方法而不是 PHP 原生方法 print_r() 或 var_dump() 来打印变量信息,因为 dd() 方法可以打印多个任何类型变量:dd($object, 123, [123, 324]);
顺便一提,所谓 dd 的意思是 dump, die,而在最新的 Laravel 6 框架中,新增了 ddd() 方法,它是 dd() 方法的升级版,意思是 dump, die, debug,你可以在这篇文章查看该方法的介绍。
打印 SQL 语句
在使用框架的 ORM 查询构造器时,可以通过 toSql() 方法输出原生 SQL 语句。
SQL 语句中的参数值由于被 ? 代替,可以使用 getBindings() 输出构造器中的查询条件:
|
|
数据库
数据库迁移
参考文档:数据库迁移
Laravel 提供了一整套的数据库迁移方案,便于开发使用代码直接创建、修改数据库的表结构,而无需繁琐地书写表结构的 SQL 语句。首先使用如下命令生成迁移文件:
|
|
然后在 /database/migrations/ 目录下找到对应的迁移文件 2019_08_29_172043_do_some_migration.php,根据业务需求设计表结构:
|
|
完成表结构设计之后执行如下命令进行数据库迁移,如果数据库配置无误的话,框架会按照迁移文件自动创建、修改表结构,完成数据库迁移操作:
|
|
数据库填充
参考文档:数据填充
后端开发最头疼的就是模拟数据了,特别是新建数据库以后还要一条一条记录手动 mock 那就太糟心了。Laravel 自带了一个数据库填充引擎,可以按照工厂填空类进行数据库填充测试数据。这里分三步走战略:
- 准备对应模型类和数据填充工厂类
- 生成数据填充执行类
- 执行填充
准备类文件
创建工厂类之前你务必要先准备好对应的 User 模型,在本例中,User 模型文件位于 /app/User.php,然后创建工厂类 /database/factories/UserFactory.php ,并为每个字段写好数据填充要求:
|
|
生成填充执行类
使用如下命令生成填充执行类文件:
|
|
修改 /database/seeds/UserTableSeeder.php 文件,约束填充的记录条数:
|
|
并在 /database/seeds/DatabaseSeeder.php 从添加需要填充的类文件:
|
|
执行填充
执行数据库填充命令收货一堆假数据:
|
|
伪造数据
可以看到上述填充类中使用了 $faker 这个玩意儿,其对应的是一个可堪使用的数据填充工具 Faker,提供了诸如电话号码、地址、邮箱、用户名、文章标题、文章摘要、文章内容、图片链接等一系列的填充项,基本能够覆盖大部分需求。关于中文数据填充的相关操作可以阅读《使用 Laravel 数据填充功能生成中文测试数据》
另外,框架自带的 Illuminate\Support\Str 也提供了很多丰富的字符串处理方法可堪使用。
查询构造器
参考文档:查询构造器
这部分没太多可说的,掌握基本的 select()、where()、whereIn()、group()、latest()、get()、paginate() 基本可以完成 80% 的工作了,需要提到的是,由于查询构造器的查询方法返回值不同,这里需要格外注意:
find($id)需要一个 id 并返回一个模型。如果不存在匹配的模型,则返回null。findOrFail($id)需要一个 id 并返回一个模型。如果不存在匹配的模型,则会引发错误,它会抛出一个error。first()返回在数据库中找到的第一条记录。如果不存在匹配的模型,则返回null。firstOrFail()返回在数据库中找到的第一条记录。如果不存在匹配的模型,则会引发错误。它会抛出一个error。
Eloquent ORM
模型
参考文档:查询构造器
在定义模型时,有两个模型类属性比较重要:
|
|
上述字段可以视为黑名单属性,对应的白名单属性为:
|
|
软删除
相关操作参见:Eloquent ORM 实例教程 —— 模型删除及软删除相关实现
某些表字段设计为软删除,而非物理删除,在模型内使用软删除,只需两步:
- 引用软删除 trait
- 增加软删除字段
引用软删除 Trait
首先在目标模型上使用 Illuminate\Database\Eloquent\SoftDeletes trait:
|
|
增加软删除字段
这一部分不再赘述,可以参照前文数据库迁移部分,新增一个软删除字段,默认新增的软删除字段名为 deleted_at。
你也可以手动修改数据库表结构增加自定义名称的软删除字段,当然,你需要在对应的模型中使用 DELETED_AT 类常量指定自定义的软删除字段名:
|
|
其他说明
一般来说,完成前述设置后已经可以正常使用软删除,当你在模型实例上使用 delete() 方法删除数据实例时,当前日期时间会写入 deleted_at 字段,表示该记录被软删除。同时,查询出来的结果也会自动排除已被软删除的记录。
需要硬删除的话使用 forceDelete() 方法即可。
为了使模型定义更加清晰,不妨在目标模型内设置类成员变量,显式指定 deleted_at 字段的类型:
|
|
当然,如果你不想将该字段的值设为删除日期,也可以对其进行改造,具体改造方式可以参阅《Laravel5软删除(SoftDeletes)的deleted_at改造》
修改器
对数据库字段的特殊处理,可以使用 Eloquent 修改器 对入库字段进行预处理,比如姓名首字母大写才能入库等等。
另外,某字段储存为 json 格式,处理时需要转换为 PHP 数组,也只需在模型内声明 $cast 属性加入 array 类型转换,当你访问的时候就会自动被转换为 PHP 数组:
|
|
游标
cursor 方法允许你使用游标遍历数据库,它只执行一次查询。处理大量的数据时, cursor() 方法可以大大减少内存的使用量,比如导入、导出数据时,如果直接 foreach 遍历变量,可能会犹豫变量太大导致内存溢出。此事使用基于迭代器的游标可以大大提升程序的鲁棒性:
|
|
关联模型
参考文档:关联模型
这一部分可以说是 Laravel 的精髓所在。框架设计的模型关联可以将多个模型之间的关联关系在 Model 中定义清楚,便于数据查询和后期维护,特别是在例如列表页、详情页等需求中轻松地获取有关联关系的将数据对象,完全无需自己手动拼接、处理数据。
举两个例子:
-
在 User 和 Post 模型中绑定关联关系后,就可以使用
$post->comments来获取该文章对应的全部评论。 -
在列表查询时,可能需要减少多次查询,避免
1+N次查询。比如文章列表:- 获取文章
- 获取每篇文章的评论
ps. 数据库中文章表为 post,评论表为 comment
如果遍历 $posts 使用关联查询 $post->comments 将造成过多不必要的 SQL 查询。假设该页有 10 条 post 记录,正常情况将执行 1+10=11 条 SQL。为解决这种多查询问题,可以使用预加载来实现最简查询。
使用时,在查询语句中使用 with() 即可,如:
|
|
- 获取关联对象的数量可以使用关联模型计数 的
withCount()方法,它将放在结果模型的{relation}_count列,如:
|
|
跨域
处理跨域问题可以考虑使用 Laravel CORS 扩展包
暂时就写这么多,上述技巧基本可以涵盖常见的 CURD 需求(滑稽。如果你有其他推荐的奇技淫巧不妨在评论区留言。