Метод attempt
Метод attempt класса RateLimiter предназначен для выполнения callback-функции с учётом ограничений по частоте вызовов. Он принимает ключ, максимальное количество попыток и время в секундах, после которого счётчик сбрасывается. Если лимит не превышен, метод выполняет переданное замыкание и увеличивает счётчик попыток. В противном случае возвращается false.
Синтаксис
<?php
use Illuminate\Support\Facades\RateLimiter;
$res = RateLimiter::attempt($key, $maxAttempts, $callback, $decaySeconds = 60);
?>
Параметры метода:
- $key - уникальный ключ для идентификации лимита (например, IP-адрес или ID пользователя);
- $maxAttempts - максимальное количество разрешённых попыток;
- $callback - замыкание, которое выполняется при успешной проверке;
- $decaySeconds - время в секундах, после которого счётчик попыток сбрасывается (по умолчанию 60).
Пример
Давайте ограничим количество попыток входа в систему для одного IP-адреса до 5 раз в минуту:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Http\Request;
class AuthController extends Controller
{
public function login(Request $request)
{
$key = $request->ip();
$maxAttempts = 5;
$decaySeconds = 60;
$res = RateLimiter::attempt($key, $maxAttempts, function () use ($request) {
// Вход выполнен успешно
return auth()->attempt($request->only('email', 'password'));
}, $decaySeconds);
if ($res) {
return redirect()->intended('/dashboard');
}
return back()->withErrors(['email' => 'Слишком много попыток входа.']);
}
}
?>
Результат выполнения кода при успешном входе:
"redirect to /dashboard"
Результат при превышении лимита:
"Слишком много попыток входа."
Пример
Используем метод attempt для ограничения отправки сообщений с одним email-адресом до 3 раз в 10 минут:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Http\Request;
class MessageController extends Controller
{
public function send(Request $request)
{
$key = 'send-message:' . $request->email;
$maxAttempts = 3;
$decaySeconds = 600;
$res = RateLimiter::attempt($key, $maxAttempts, function () use ($request) {
// Отправка сообщения
Mail::to($request->email)->send(new WelcomeMail());
return true;
}, $decaySeconds);
if ($res) {
return response()->json(['message' => 'Сообщение отправлено.']);
}
$seconds = RateLimiter::availableIn($key);
return response()->json([
'message' => 'Слишком много попыток. Повторите через ' . $seconds . ' секунд.'
], 429);
}
}
?>
Результат выполнения кода при успешной отправке:
"Сообщение отправлено."
Результат при превышении лимита:
"Слишком много попыток. Повторите через 589 секунд."
Пример
Рассмотрим использование attempt в маршруте с применением промежуточного слоя для защиты API-эндпоинта:
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Http\Request;
Route::post('/api/submit', function (Request $request) {
$key = 'submit-form:' . $request->ip();
$maxAttempts = 10;
$decaySeconds = 60;
$res = RateLimiter::attempt($key, $maxAttempts, function () use ($request) {
// Обработка данных формы
$data = $request->validate([
'name' => 'required|string',
'email' => 'required|email',
]);
return $data;
}, $decaySeconds);
if ($res) {
return response()->json(['success' => true, 'data' => $res]);
}
return response()->json([
'error' => 'Превышен лимит запросов.'
], 429);
});
?>
Результат выполнения кода при успешной обработке:
["success" => true, "data" => ["name" => "John", "email" => "john@example.com"]]
Результат при превышении лимита:
"Превышен лимит запросов."
Смотрите также
-
метод
tooManyAttempts,
который проверяет, превышен ли лимит попыток -
метод
hit,
который увеличивает счётчик попыток без выполнения действия -
метод
remaining,
который возвращает оставшееся количество попыток -
метод
availableIn,
который возвращает время до сброса счётчика в секундах