inigopascall/spamguard
Laravel package to help detect and block spam in forms and user submissions. Adds simple anti-spam checks and validation hooks to reduce bot signups and junk messages, with easy configuration for common use cases.
Installation
composer require inigopascall/spamguard
Publish the config file (if needed):
php artisan vendor:publish --provider="InigoPascall\Spamguard\SpamguardServiceProvider" --tag="spamguard-config"
Basic Usage
Add the Spamguard middleware to your form request route:
Route::post('/contact', [ContactController::class, 'store'])
->middleware('spamguard');
First Test
Submit a form with a known spam pattern (e.g., test@example.com as email). The middleware will block it if configured.
config/spamguard.php (default rules, thresholds, and exceptions).app/Http/Middleware/Spamguard.php (customize logic if needed).tests/ for edge cases (e.g., false positives/negatives).// In ContactController.php
public function store(Request $request) {
$request->validate([...]);
// Spamguard runs automatically via middleware.
// If blocked, returns 429 Too Many Requests.
return response()->json(['success' => true]);
}
Leverage built-in rules (e.g., email, ip, user_agent) or extend them:
// config/spamguard.php
'rules' => [
'email' => [
'patterns' => ['test@example.com', 'spam@domain.com'],
'max_attempts' => 3,
],
'ip' => [
'blocked_ips' => ['192.168.1.100'],
],
],
Create a custom rule class:
// app/Rules/CustomSpamRule.php
use InigoPascall\Spamguard\Rules\SpamguardRule;
class CustomSpamRule extends SpamguardRule {
public function passes($attribute, $value) {
return !str_contains(strtolower($value), 'free offer');
}
}
Register it in config/spamguard.php:
'rules' => [
'custom' => [
'class' => \App\Rules\CustomSpamRule::class,
'fields' => ['message'],
],
],
Laravel Collective: Add spamguard to $middleware in FormRequest:
public function rules() {
return [...];
}
public function authorize() {
return true;
}
public function middleware() {
return ['spamguard'];
}
Livewire/Alpine: Use AJAX with 429 handling:
form.submit(e => {
e.preventDefault();
fetch('/submit', { method: 'POST', body: formData })
.then(res => {
if (res.status === 429) showSpamWarning();
});
});
Enable logging in config/spamguard.php:
'log_blocked_attempts' => true,
View logs in storage/logs/laravel.log or integrate with a monitoring tool.
False Positives
max_attempts or whitelist IPs/emails.email rules if they reuse a test address.Performance Overhead
fields to target specific inputs:
'rules' => [
'message' => [
'patterns' => ['/spam keywords/i'],
],
],
Middleware Order
spamguard before throttle or validate to avoid unnecessary processing:
Route::post('/contact', [...])
->middleware(['spamguard', 'throttle:10']);
Rate-Limiting Quirks
tooManyAttempts response. Customize it in app/Exceptions/Handler.php:
public function render($request, Throwable $exception) {
if ($exception instanceof \Illuminate\Cache\RateLimitingException) {
return response('Spam detected. Try again later.', 429);
}
return parent::render($request, $exception);
}
Check Blocked Attempts
Run php artisan spamguard:clear to reset test data.
Inspect the spamguard table (if using database storage):
SELECT * FROM spamguard_attempts WHERE field='email' AND value='test@example.com';
Disable Rules Temporarily
Set 'enabled' => false in config/spamguard.php for testing.
Custom Responses Override the middleware response:
// app/Http/Middleware/Spamguard.php
public function handle($request, Closure $next) {
if ($this->isSpam($request)) {
return response()->json(['error' => 'Custom spam message'], 429);
}
return $next($request);
}
Database Storage
Configure storage in config/spamguard.php to use database instead of cache:
'storage' => 'database',
Run migrations:
php artisan migrate
Event Listeners
Listen for spamguard.blocked events to trigger actions (e.g., email alerts):
// app/Providers/EventServiceProvider.php
protected $listen = [
\InigoPascall\Spamguard\Events\SpamBlocked::class => [
\App\Listeners\LogSpamAttempt::class,
],
];
API Integration
Use the package’s Spamguard facade directly in controllers:
use InigoPascall\Spamguard\Facades\Spamguard;
if (Spamguard::isSpam($request)) {
abort(429);
}
How can I help you explore Laravel packages today?