前言
虽然开发了几年,但一直没有使用 Laravel
作为项目框架,在 Laravel
里,属于不折不扣的新人,正好新项目用了 Laravel
,在这分享一下 Laravel
开发 API
心得,希望能给想使用 Laravel
开发的人带来帮助。
通过实现「用户注册」接口,来介绍每个功能的使用场景。
PS:「用户注册」接口纯粹是为了方便介绍,所以没有使用自带的 Auth 模块.
大纲
- 开发环境
- 项目搭建
- 目录结构
- 路由加载
- API 规范
- Enum 枚举
- 表单场景验证
- 事件监听
- 用户注册
- Eloquent 条件查询
- 模型事件
- 队列
- Passport OAuth 认证
- 资料
- 补充点
- 升级8.x
开发环境
1 | Docker - PHP7.4 + MySQL5.7 + Nginx1.19 |
项目搭建
一、安装 Laravel
1 | $ composer create-project --prefer-dist laravel/laravel:^6.2 test |
二、Laravel
- User
相关文件处理
1) 删除以下文件
1 | app/Http/Controllers/Auth 目录 |
2) 移动 app/User.php
到 app/Models/User/User.php
三、配置
1) .env
- 配置数据库
1 | DB_CONNECTION=mysql |
2) config/app.php
- 配置时区
1 | 'timezone' => 'Asia/Shanghai' |
四、中间件 AcceptHeader
Accept 决定了响应返回的格式,设置为 application/json, 遇到的所有报错 Laravel 会默认处理为 JSON 格式
1) 新建 app/Http/Middleware/AcceptHeader.php
1 |
|
2) app/Http/Kernel.php
1 | ... |
五、创建 users
表
1) 创建迁移
1 | php artisan make:migration create_users_table --create=users |
2) 编辑 database/migrations/2021_04_29_070350_create_users_table.php
1 |
|
3) 执行迁移
1 | $ php artisan migrate |
六、安装扩展包
1) laravel-ide-helper
- IDE 智能提示插件
1 | $ composer require "barryvdh/laravel-ide-helper:2.8.*" --dev |
2) laravel-telescope
- 调试工具
1 | $ composer require "laravel/telescope:^3.0" --dev |
七、取消扩展包自动发现,并在 AppServiceProvider
注册
1) composer.json
1 | ... |
2) app/Providers/AppServiceProvider.php
- 仅本地环境注册服务
1 | ... |
目录结构
- app 目录
Console - 自定义的 Artisan 命令目录
Enums - 枚举目录
Exceptions - 异常处理目录
Http - 包含控制器、中间件以及表单请求等目录
Jobs - 队列任务目录
Libraries - 第三方包目录(包含扩展包封装类)
Listeners - 事件监听目录
ModelFilters - 模型过滤器目录
Models - 模型目录
Observers - 模型观察者目录
Providers - 服务提供者目录
Services - 业务服务类目录 - route 目录
api - 接口目录
路由加载
1) 删除 routes/api.php
& routes/web.php
路由文件
2) 编辑 app/Providers/RouteServiceProvider.php
, 加载 routes/api
目录下的路由文件
1 |
|
3) 新建「路由」 routes/api/user.php
1 |
|
4) 新建「控制器」 app/Http/Controllers/V1/User/UserController.php
1 |
|
API规范
参考 Jiannei/laravel-response
由于个人并不太喜欢用RESTful
规范的HTTP
状态码以及Enum
的定义, 就整了个新包 sevming/laravel-response, 默认HTTP
返回状态码为200
1) 安装
1 | $ composer require sevming/laravel-response:^1.0.2 |
2) 编辑 app/Exceptions/Handler.php
1 | class Handler extends ExceptionHandler |
Enum枚举
1) 新建 app/Enums/ResponseEnum.php
1 |
|
2) 编辑 app/Http/Controllers/V1/User/UserController.php
1 | ... |
3) POST
请求 /v1/user/register
1 | { |
表单场景验证
1) 新建「表单验证基类」 app/Http/Requests/FormRequest.php
1 |
|
2) 新建 app/Http/Requests/SceneValidator.php
1 |
|
3) 新建「请求类」 app/Http/Requests/User/UserRequest.php
1 |
|
4) 编辑 app/Http/Controllers/V1/User/UserController.php
1 | ... |
5) POST
请求 /v1/user/register
1 | # 请求数据 |
6) 安装 overtrue/laravel-lang
- 语言包
1 | composer require "overtrue/laravel-lang:~3.0" |
7) 重新请求接口,返回数据如下:
1 | { |
事件监听
QueryListener - SQL 日志记录
1) 新建 app/Listeners/QueryListener.php
1 |
|
2) 编辑 app/Providers/EventServiceProvider.php
1 |
|
用户注册
1) 新建「腾讯地图类」 app/Libraries/TencentMapLibrary.php
1 |
|
2) 新建「服务类」 app/Services/User/UserService.php
1 |
|
3) 编辑 app/Models/User/User.php
1 |
|
4) 编辑 app/Enums/ResponseEnum.php
1 | ... |
5) 编辑 app/Http/Controllers/V1/User/UserController.php
1 |
|
Eloquent条件查询
1) 安装
1 | $ composer require tucker-eric/eloquentfilter:^2.4 |
2) 新建 app/Models/ModelTrait.php
1 |
|
3) 新建「模型过滤类」 app/ModelFilters/User/UserFilter.php
1 |
|
4) 编辑 app/Models/User/User.php
1 | ... |
模型事件
优化用户注册时的地址获取
1) 新建「观察者类」 app/Observers/User/UserObserver.php
1 |
|
2) 编辑 app/Models/User/User.php
1 | ... |
3) 编辑 app/Services/User/UserService.php
1 | ... |
队列
用户注册地址获取修改为队列方式
1) .env
队列配置
1 | QUEUE_CONNECTION=redis |
2) 新建「任务类」 app/Jobs/User/UserLocation.php
1 |
|
3) 编辑 app/Observers/User/UserObserver.php
1 |
|
4) 开启队列监听
1 | $ php artisan queue:listen |
Passport认证
实现用户注册后返回 Token, 以及删除无效 Token
1) 安装 & 配置
1 | $ composer require laravel/passport:^9.4.0 |
2) .env
配置, 保存刚刚生成的「个人客户端」CLIENT_ID
& CLIENT_SECRET
1 | PASSPORT_PERSONAL_ACCESS_CLIENT_ID=1 |
3) 配置 app/Providers/AuthServiceProvider.php
, 设置 TOKEN
有效期一周
1 | ... |
4) 编辑 app/Providers/EventServiceProvider.php
监听 Token
创建事件
1 | ... |
5) 新建 app/Listeners/PassportAccessTokenCreated.php
删除过期 Token
1 |
|
6) 编辑 app/Models/User/User.php
1 | ... |
7) 编辑 app/Observers/User/UserObserver.php
1 | ... |
8) 编辑 app/Http/Controllers/V1/User/UserController.php
1 | ... |
使用 Token
作为用户的登录凭证
1) 编辑 routes/api/user.php
1 |
|
2) 编辑 app/Http/Controllers/V1/User/UserController.php
1 | ... |
3) 编辑 config/auth.php
1 | return [ |
4) Postman
配置 Header
1 | Authorization: Bearer {token} |
4) GET
请求接口 /v1/user/mock
, 可以看到用户的信息
5) 通过查看 SQL
日志, 发现 Passport
查询语句太多了, 安装 overtrue/laravel-passport-cache-token, 支持配置缓存方式,具体可查看包文档说明
1 | $ composer require overtrue/laravel-passport-cache-token:^2.1 |
资料
1) 底层原理
- 服务容器
Laravel 学习笔记 —— 神奇的服务容器
Laravel 服务容器的初始化 - 中间件
Laravel 中间件原理 - 管道流
Laravel 管道流原理
Laravel Pipeline 组件的实现原理 - 异常处理
Laravel 源码阅读指南–异常处理
Laravel Exceptions——异常与错误处理 - 队列
剖析 Laravel 队列系统–Worker - 认证
Laravel 认证原理及完全自定义认证 - 其它原理
leoyang 的博客
Laravel之道
2) 架构
- 基于 Module 的 Laravel API 架构
- Laravel 模块化开发
- 打造 Laravel 优美架构 谈可维护性与弹性设计
- Laravel 程序架构设计思路:使用动作类
- 什么?快来开启 MVC 的拓展模式
- 程序架构讨论:你的应用就是一个扩展的容器
- Laravel - 服务设计模式
- 如何使用Service模式
- 关于 Repository 的设计模式
- 在 Laravel 5.8 中正确地应用 Repository 设计模式
3) API 规范相关讨论
4) 表单场景验证
5) 模型相关
- 如何更快的找到自己所需的模型关联类型?
- Laravel Eloquent 模型关联速查表
- 模型关联给我们带来了哪些便利
- Laravel 模型过滤(Filter)设计
- 关于模型全局作用域是否支持动态传参?
- 对于项目中简单的多条件查询的一些心得体会
- whereHas性能调优——采用 where in 语法实现优化 查询关联
- 给 Eloquent 的 whereHas 加个 where in 的优化
- 如何注册一个最后执行的模型事件监听器
- ORM Observer 使用小结
6) API 资源
7) 队列
补充点
1) 关于 PhpStorm
中 Laravel
的路由跳转 (Windows
下 Ctrl
+ 鼠标左键
点击路由跳转至对应控制器),Demo
中无法跳转问题
编辑
routes/api/user.php
1
2
3
4
5
6
7
8
Route::group([
'prefix' => 'user',
'namespace' => 'User'
'as' => 'user.',
], function () {
...
});重新生成
ide-helper.php
1
$ php artisan ide-helper:generate
2) 跨域
安装
fruitcake/laravel-cors
1
2$ composer require "fruitcake/laravel-cors:^2.0"
$ php artisan vendor:publish --tag="cors"编辑
app/Http/Kernel.php
1
2
3
4
5
6
7...
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
...
];
...编辑
config/cors.php
- 查看更多配置1
'paths' => ['v1/*']
3) 添加模型 saveQuietly
方法 - 保存给定的模型而不触发任何事件 (Laravel 8.x 框架自带
)
- 编辑
app/Models/ModelTrait.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15...
/**
* Save the model to the database without raising any events.
*
* @param array $options
*
* @return bool
*/
public function saveQuietly(array $options = [])
{
return static::withoutEvents(function () use ($options) {
return $this->save($options);
});
}
...
升级8.x
直接安装 8.x 版本, 再按文档搭项目,相关包版本变化如下:
laravel/laravel:^6.2
to^8.4.0
barryvdh/laravel-ide-helper:2.8.*
to^2.10
laravel/telescope:^3.0
to^4.4
1
2# migrations 路径变更
php artisan migrate --path=./vendor/laravel/telescope/database/migrations/overtrue/laravel-lang:~3.0
to~5.0
1
2
3
4
5
6
7# 编辑 config/app.php
# 与 3.0 版本不同, 这个无需替换服务提供者
Illuminate\Translation\TranslationServiceProvider::class
# 配置语言
'locale' => 'zh_CN'tucker-eric/eloquentfilter:^2.4
to^3.0
laravel/passport:^9.4.0
to^10.1
1
# 与 9.x 版本不同, 不需要在 `AuthServiceProvider` 配置 personalAccessClientId(), 且此方法在新版本的包中已移除
sevming/laravel-response:^1.0.2
to^1.0.3
fruitcake/laravel-cors
- 无需安装,框架自带app/Models/ModelTrait
=>saveQuietly
不需要添加,框架自带