composer require bxnxg/antispam-bundle
config/bundles.php:
return [
// ...
Bxnxg\AntiSpamBundle\BxnxgAntiSpamBundle::class => ['all' => true],
];
php bin/console config:dump-reference BxnxgAntiSpamBundle
Override in config/packages/bxnxg_antispam.yaml:
bxnxg_antispam:
enabled: true
honeypot:
enabled: true
field_name: 'honeypot_field'
captcha:
enabled: false
# (Configure if enabling)
Add Honeypot to a Form:
// src/Form/ContactType.php
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class ContactType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class)
->add('email', TextType::class)
->add('message', TextType::class)
->add('honeypot_field', HiddenType::class, [
'mapped' => false,
'required' => false,
]);
}
}
Validate Submission: The bundle automatically checks for honeypot submissions. No extra validation code needed.
Honeypot Integration:
honeypot_field).CAPTCHA Integration (Optional):
bxnxg_antispam:
captcha:
enabled: true
provider: 'recaptcha' # or 'hcaptcha'
recaptcha:
site_key: '%env(RECAPTCHA_SITE_KEY)%'
secret_key: '%env(RECAPTCHA_SECRET_KEY)%'
$builder->add('captcha', CaptchaType::class);
Custom Validation:
// src/Validator/Constraints/CustomAntiSpam.php
use Symfony\Component\Validator\Constraint;
class CustomAntiSpam extends Constraint {
public $message = 'This submission looks like spam.';
}
// src/Validator/CustomAntiSpamValidator.php
use Symfony\Component\Validator\ConstraintValidator;
class CustomAntiSpamValidator extends ConstraintValidator {
public function validate($value, Constraint $constraint) {
// Custom logic (e.g., IP rate limiting, keyword checks)
}
}
$builder->add('message', TextType::class, [
'constraints' => [new CustomAntiSpam()],
]);
Event-Based Extensions:
// src/EventListener/AntiSpamListener.php
use Bxnxg\AntiSpamBundle\Event\SpamDetectedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AntiSpamListener implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
SpamDetectedEvent::NAME => 'onSpamDetected',
];
}
public function onSpamDetected(SpamDetectedEvent $event) {
// Log, block IP, or notify admin
$event->setHandled(true); // Prevent default response
}
}
{{ form_row(form.honeypot_field, { 'attr': { 'style': 'display:none;' } }) }}
SpamChecker service directly:
$spamChecker = $container->get('bxnxg_antispam.spam_checker');
if ($spamChecker->isSpam($request)) {
throw new \Symfony\Component\HttpKernel\Exception\HttpException(403, 'Spam detected');
}
SpamChecker service in PHPUnit:
$this->container->set('bxnxg_antispam.spam_checker', $this->createMock(SpamCheckerInterface::class));
Honeypot Field Naming:
honeypot_field. If you rename it, update the config:
bxnxg_antispam:
honeypot:
field_name: 'custom_honeypot'
CAPTCHA Configuration:
captcha.enabled is true but no provider is configured, the bundle will throw an exception.provider and required keys (e.g., recaptcha.site_key).Double Validation:
Event Handling:
SpamDetectedEvent is dispatched after validation fails. If you set $event->setHandled(true), the default response (e.g., 403) will be suppressed.Performance:
bxnxg_antispam:
captcha:
recaptcha:
cache_response: true
Enable Debug Mode:
debug: true in config to log spam attempts:
bxnxg_antispam:
debug: true
var/log/dev.log.Validate Manually:
SpamChecker service to debug submissions:
$spamChecker = $container->get('bxnxg_antispam.spam_checker');
$isSpam = $spamChecker->isSpam($request);
dump($spamChecker->getSpamReasons());
Common Issues:
display: none is overridden by JS).
Fix: Use type="hidden" and ensure no JS modifies it.site_key or secret_key in config.
Fix: Verify keys match your CAPTCHA provider’s settings.Custom Spam Checks:
SpamChecker service:
// src/Service/CustomSpamChecker.php
use Bxnxg\AntiSpamBundle\SpamChecker\SpamCheckerInterface;
class CustomSpamChecker implements SpamCheckerInterface {
private $decorated;
public function __construct(SpamCheckerInterface $decorated) {
$this->decorated = $decorated;
}
public function isSpam(Request $request): bool {
$isSpam = $this->decorated->isSpam($request);
// Add custom logic (e.g., check for suspicious keywords)
if (str_contains($request->request->get('message'), 'free offer')) {
$isSpam = true;
}
return $isSpam;
}
}
config/services.yaml:
services:
Bxnxg\AntiSpamBundle\SpamChecker\SpamChecker:
decorates: 'bxnxg_antispam.spam_checker'
arguments: ['@bxnxg_antispam.spam_checker.inner']
Override Templates:
templates/bxnxg_antispam/:
How can I help you explore Laravel packages today?