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 需求(滑稽。如果你有其他推荐的奇技淫巧不妨在评论区留言。