PHP防抖(防重复提交)简单实现
PHP防抖(防重复提交)简单实现
本文编写时间:2023-06-05
需求
前端有时表单未做防抖处理,会给后端同时传递重复请求,希望后端代码能屏蔽。
实现:
这里给出本人的非常简单的实现。主要是针对简单需求的。复杂的需求代码肯定没这么简单。
前提:需安装redis。
欢迎各种讨论。
代码部分
仅供参考
异常类
/**
* 防抖异常。这个类留空就行。
*/
class AntiRepeatException extends Exception
{
}
//下面:框架的异常集中处理,自定义 的。这里是tp的。larave类似。
namespace app\common\exception;
use Exception;
use think\exception\Handle;
class MyException extends Handle
{
public function render(Exception $e)
{
// 参数验证错误
if ($e instanceof AntiRepeatException) {
return json([ 'code'=>420, 'msg'=>$e->getMessage() ])
}
// 其他错误交给系统处理
return parent::render($e);
}
}
下面是通用的防抖类。
namespace app\services\system;
use app\common\exception\AntiRepeatException;
use app\services\Redis;
/**
* 通用.
*
*
* @author
*/
class AntiRepeat
{
/**
* php 防抖通用方法。
*
* @param int $user_id 用户id,如设置成0,则表示后端对所有该控制器的请求,无差别限流。
* @param int $cycle 周期,单位秒,一个周期内只允许一个请求。
* @throws AntiRepeatException
*/
public static function handle($user_id = 0, $cycle = 5)
{
//域名,注意,这几个参数应该使用各个框架自己提供的,这里是tp示例。
$host = request()->host();
//端口
$port = request()->port();
// 模块名
$modules = request()->module();
// 控制器名称
$controller = request()->controller();
// 方法名称
$method = request()->action();
$key = 'antiRepeat:' . $host . ':' . $port.":" .$modules . ':' .
$controller . ':' . $method . ':' . $user_id;
$redis = Redis::getInstance();
if ($redis->get($key) == '1') {
throw new AntiRepeatException('请不要提交重复请求');
} else {
$redis->setex($key, $cycle, 1);
}
}
}//end class
下面是使用示例
class TestController extends Controller
{
// 假设该控制器的方法需要对登录用户限流 or 防抖。
public function index444()
{
$user_id = Auth::id();// 得到当前登录用户。
AntiRepeat::handle($user_id);
// 下面做该接口正常的功能实现。
// 。。。
// 。。。
return 'ok';
}
}
总结
- 这代码只能应付简单的需求,用于一些用户下订单之类的重要操作。
- 限流是大概念,防抖可以看成某种简单的限流实现。
- 即可针对单个登录用户,也可以对所有请求,但实际后者意义不大。
- 后端独立实现,无需前端配合
本作品采用《CC 协议》,转载必须注明作者和本文链接
Laravel 天然提供了一个
Cache::lock
的操作。setNx
我自己做了一个功能,每次用户提交的POST数据都保存在sqlite数据库里面, 然后提交的时候,从sqlite的里面搜索,按用户ID,IP地址,和间隔时间来搜索判断,
优点是: 1、保存和记录了用户提交的所有记录,后台可备查,万一系统崩溃,数据也可恢复,而且这个也是可靠的原始数据,可以审计备查, 2、可以按时间参数来控制重复,比如24小时内禁止重复提交,或者3分钟内禁止提交 3、可以控制重复提交的次数,比如,可以24小时内重复提交3次,比如某些投票的应用,
假如很多方法都这样额外加一句 个人觉得不太灵活,用注解会不会好一点,或者一个基类属性来控制 $user_id = Auth::id();// 得到当前登录用户。 AntiRepeat::handle($user_id);