我的用户表上有一个信用字段,每个用户请求对网站API递减1。 而不是在我考虑使用缓存的每个请求上读/写数据库。
所以在第一次请求时我抓住了积分,随后的请求我将缓存值减1,然后在某个时刻更新db ...
所以我创建了一个基本上做的中间件:
public function handle($request, Closure $next)
{
// check api key
$user = User::where(['api_token' => $request->input('license')])->first();
if( ! $user )
return \Response::json(['error' => 'The provided License key is not valid.'], 403);
// check credits
$cache_key = 'user_'.$user->id.'_credits';
$credits = Cache::remember( $cache_key, 1, function ($u) use ($user) {
return $u->credits;
});
$credits::decrement($cache_key);
//update db on cache expiration ?
return $next($request);
}
但是现在我不确定何时应该使用新的缓存值更新数据库,或者这是否是一个很好的做法?
我基本上都试图在每次请求时通过缓存而不是数据库。
更新 检查@antonio后,我的功能会像下面的代码一样结束。我看到的问题是,在缓存过期之前,$ model->信用不会更新。但是我需要在每次通话时检查用户是否消耗了比他们更多的积分,或者看看我是否启动了自动购买活动。
public function handle($request, Closure $next)
{
// Create a cache key based on the license
$cache_key = 'user_'.($license = $request->input('license'));
// Remember will return a cached user if the license is cached
$model = Cache::remember($cache_key, 1, function () use ($license) {
// find the user by the license
if(! $user = User::where(['api_token' => $license])->first()) {
// This license does not exists, return a response instead
return \Response::json(['error' => 'The provided License key is not valid.'], 403);
}
// return the user or response
return $user;
});
// If it is a response, break and return it
if ($model instanceof Response || $model instanceof JsonResponse ) {
return $model;
}
// TODO Validate domain
//dd($_SERVER['HTTP_REFERER']); or use CORS or embed site_url in request?
// Decrement the credits
$model::decrement('credits');
// Autobuy zone
if( $model->credits == $model->auto_buy_amount )
event( new CreditsLimitReached($model) );
// No more credits
if( $model->credits < 1 && ! $model->nocredits_email ){
$model->nocredits_email = true;
$model->save();
// TODO clean no credits emails every day
event( new OutOfCredits($model) );
return \Response::json(['error' => 'You run out of credits.'], 403);
}
// Go to the next middleware
return $next($request);
}
也许我的问题应该是你如何编写这样的代码。 基本上,当用户执行api调用时,我需要在此中间件上执行3个任务 1-减1学分 2-检查用户是否已达到自动购买区和火灾事件 3-检查用户是否用完了积分和火灾事件一次(基本上是电子邮件让他们知道用完了积分)
答案 0 :(得分:1)
如果您需要在数据库中更新数据,那么您唯一能做的就是不要一遍又一遍地寻找用户来保存一个请求:
public function handle($request, Closure $next)
{
// Create a cache key based on the license
$cache_key = 'user_'.($license = $request->input('license')).'_credits';
// Remember will return a cached user if the license is cached
$model = Cache::remember($cache_key, 1, function () use ($license) {
// find the user by the license
if(! $user = User::where(['api_token' => $license])->first()) {
// This license does not exists, return a response instead
return \Response::json(['error' => 'The provided License key is not valid.'], 403);
}
// return the user
return $user;
});
// If it is a response, break and return it
if ($model instanceof Response) {
return $model;
}
// Decrement the credits
$model::decrement('credits');
// Go to the next middleware
return $next($request);
}