N+1 问题捕杀神器 ——beyondcode/laravel-query-detector
安装
1 | composer require beyondcode/laravel-query-detector --dev |
将配置文件发布出来:
1 | php artisan vendor:publish --provider=BeyondCode\\QueryDetector\\QueryDetectorServiceProvider |
提示方式:
修改一下配置 config/querydetector.php
1 | 'output' => [ |
- \BeyondCode\QueryDetector\Outputs\Alert::class —— 浏览器 Alert 提示;
- \BeyondCode\QueryDetector\Outputs\Console::class —— 浏览器 console 提示;
- \BeyondCode\QueryDetector\Outputs\Clockwork::class —— 浏览器 clockwork 插件提示,该扩展包的安装建 课程;
- \BeyondCode\QueryDetector\Outputs\Debugbar::class —— Laravel-Debugbar 提示;
- \BeyondCode\QueryDetector\Outputs\Json::class —— json 响应提示,由于 LaraBBS 中使用了 Dingo 扩展包完成接口数据的返回,该配置对现有接口没有作用。任何继承了
Illuminate\Http\JsonResponse
的响应都会自动添加提示; - \BeyondCode\QueryDetector\Outputs\Log::class —— 日志提示;
白名单功能
扩展包还提供了白名单的功能,也就当某个模型的的某个关系出现了 N + 1 问题的时候,不进行报错。相当于手动取消了对某个模型预加载的监控,或许你会在某个特殊的场合遇到这样的白名单使用场景,我们只是来测试一下功能。调整一下白名单的配置:config/querydetector.php
1 | . |
哈希数据 ID —— vinkla/hashids
普通项目中,我们使用的数据 ID 通常为数据库的自增 ID,自增 ID 有一些问题:
- 数据的 ID 是暴露的;
- 有可能被别人恶意采集;
- 容易根据 ID 猜测数项目中的数据量;
- 随着数据的增长,ID 会越来越大,无法统一长度。
vinkla/hashids 是 hashids 在 Laravel 中的封装,hashids 是一个可以通过数字生成简短,唯一,无序字符串的开源库,它不仅能将数字转换为字符串,还能将转换后的结果转换回数字,利用这一点,我们可以很好的解决上述问题。
安装
1 | composer require vinkla/hashids |
安装成功后需要将
vinkla/hashids
的配置文件发布出来:
1 | php artisan vendor:publish --provider="Vinkla\Hashids\HashidsServiceProvider" |
vinkla/hashids
的思路是将数字转换为字符串,同时又可以将字符串再转换回数字。为了保证字符串不被轻易的破解,我们需要配置盐(salt),也就是给目标数字额外增加一些变量,保证他人在没有相同盐(salt)的情况下,无法将符串再转换回数字,增加了安全性。同时我们还可以指定转换后字符串的最小长度,这样能保证 ID 尽量统一美观。
在配置文件中修改
salt
和length
信息:config/hashids.php
1 | . |
vinkla/hashids
提供了多套配置信息,默认使用的是 main
中的配置,方便我们根据不同场景做不同的转换。我们现在的需求使用默认的即可,所以修改 main
中的 salt
为 larabbs
, 修改 lentgh
为 9
。
使用 -> 测试
我们先使用 Tinker 来验证一下相关的功能是否好用,打开 Tinker:
1 | php artisan tinker |
输入如下内容:
1 | $hashId = Hashids::encode(10); |
可以看到对 10 encode
的结果为 9 位,将转换后的字符串进行 decode
可以正确得到数字 10,不过这里要注意,decode
后的结果为数组。转换后的结果为什么是数组呢?因为 hashids
不仅支持数字和字符串,还支持将数组进行 encode
。
封装的方法
1 | /** |
解决跨域问题( CORS )——barryvdh/laravel-cors
同源策略
首先需要了解一下浏览器 同源策略,它是浏览器最核心也最基本的安全功能,同源的意思是,域名,协议,端口都相同。如果两个地址不同源,那么:
- Cookie、LocalStorage 和 IndexDB 无法相互读取;
- DOM 无法相互获得;
- AJAX 请求不能相互发送。
举个例子,larabbs.test 和 laravel-china.org 是无法读取对方的 Cookie 等数据,无法获取对方的 DOM,无法相互发送 AJAX 请求的。
这是出于安全的考虑,但是有的时候我们又确实需要跨域,比如要实现前后端分离,前端的域名是 www.larabbs.test 服务器接口的域名是 api.larabbs.test ,因为子域不同,依然会被同源策略限制,所以前端的 JS 就无法请求到后端接口的数据,我们需要解决这样的跨域问题。
CORS
CORS 是一个 W3C 标准,全称是 “跨域资源共享”(Cross-origin resource sharing),就是其中一种用来解决浏览器跨域的问题方法。这种方法的关键是在于服务器,只要服务器端返回了合适的头信息(Header),前端 JS 发送 AJAX 的时候就能访问跨域的资源你,代码和同源时一致,无需做任何修改,用户也不会有感知。
对于 CORS 请求时,又会分为两种,简单请求和非简单请求。
只要同时满足以下两大条件,就属于 简单请求:
- 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
- HTTP 的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
安装
1 | composer require barryvdh/laravel-cors |
将配置文件发布出来:
1 | php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider" |
使用
扩展包的使用是非常简单的,在需要的地方增加中间件即可。
如果需要全局使用,可以在 app/Http/Kernel.php
的 $middleware
中增加 \Barryvdh\Cors\HandleCors::class
,但是 LaraBBS 中只有接口部分设计到 CORS 问题,我们只添加到 API 相关的路由中。
由于 LaraBBS 中使用了 DingoApi,路由部分被接管了,所以需要去 routes/api.php
中单独设置中间件。
首先需要设置一下该中间件的别名,方便使用:app/Http/Kernel.php
1 | protected $routeMiddleware = [ |
在接口中增加 cors
中间件:routes/api.php
1 | $api->version('v1', [ |
配置
可以看到只要使用了中间件,所有的请求都是可以通过的,也就是说,barryvdh/laravel-cors
的默认配置都是允许所有请求,当然我们可以修改这些配置:config/cors.php
1 | 'supportsCredentials' => false, |
分别对应如下配置:
配置 | 对应的 Header | 说明 |
---|---|---|
supportsCredentials | Access-Control-Allow-Credentials | 是否携带 Cookie |
allowedOrigins | Access-Control-Allow-Origin | 允许的域名 |
allowedOriginsPatterns | Access-Control-Allow-Origin | 通过正则匹配允许的域名 |
allowedHeaders | Access-Control-Allow-Headers | 允许的 Header |
allowedMethods | Access-Control-Allow-Methods | 允许的 HTTP 方法 |
exposedHeaders | Access-Control-Expose-Headers | 除了 6 个基本的头字段,额外允许的字段 |
maxAge | Access-Control-Max-Age | 预检请求的有效期 |
根据实际需要修改配置即可。
以上扩展教程出自laravel社区的 Liyu 和 Summer 所作,我只是针对我项目所需扩展做一总结,非常感谢两位大佬提供的教程,让我少走好多弯路。
如有侵权,请联系博主,立马删除。