Install the Bundle
composer require andanteproject/recaptcha-bundle
Symfony Flex will auto-register the bundle in config/bundles.php.
Configure Keys
Add your Google reCAPTCHA v2 keys to config/packages/andante_re_captcha.yaml:
andante_re_captcha:
secret: '%env(RECAPTCHA_SECRET)%'
site_key: '%env(RECAPTCHA_SITE_KEY)%'
Store keys in .env:
RECAPTCHA_SECRET=your_secret_key
RECAPTCHA_SITE_KEY=your_site_key
Add to a Form
Include ReCaptchaType in your form builder:
use Andante\ReCaptchaBundle\Form\ReCaptchaType;
$builder->add('recaptcha', ReCaptchaType::class);
Test in Dev
Disable validation in andante_re_captcha.yaml for testing:
andante_re_captcha:
enable_validation: false
Basic Form Integration Add reCAPTCHA to any form (e.g., contact, registration):
$builder->add('recaptcha', ReCaptchaType::class, [
'mapped' => false, // Typically not mapped to an entity
'label' => 'Verify you are human',
]);
Theming & Styling Customize appearance via options:
$builder->add('recaptcha', ReCaptchaType::class, [
'theme' => 'dark', // 'light' (default) or 'dark'
'size' => 'compact', // 'normal' (default) or 'compact'
]);
Conditional Validation Disable validation for specific forms (e.g., API submissions):
$builder->add('recaptcha', ReCaptchaType::class, [
'constraints' => [new NotBlank()], // Only NotBlank, no reCAPTCHA
]);
Dynamic Key Management
Override keys per environment (e.g., config/packages/dev/andante_re_captcha.yaml):
andante_re_captcha:
site_key: 'dev_site_key'
secret: 'dev_secret_key'
Event-Driven Customization Extend validation logic via events (e.g., pre-submit checks):
// src/EventListener/RecaptchaListener.php
public function onKernelRequest(GetResponseEvent $event) {
if ($event->isMainRequest() && $event->getRequest()->isXmlHttpRequest()) {
$this->container->get('andante_re_captcha.manager')->disableValidation();
}
}
Validation Timing
Environment-Specific Keys
.env or config files will cause silent failures. Test with enable_validation: false first.Constraint Overrides
constraints entirely removes all validation (including NotBlank). Explicitly define alternatives:
'constraints' => [new NotBlank(), new Assert\Callback([$this, 'customValidation'])]
Caching Issues
google/recaptcha package’s verify() method directly for debugging:
$response = $this->container->get('andante_re_captcha.manager')->verify($token);
Dark Mode Quirks
dark theme may clash with custom CSS. Inspect the generated HTML (<div class="g-recaptcha">) to override styles.Log Validation Errors Extend the validator to log failed tokens:
// src/Validator/Constraint/RecaptchaValidator.php
public function validate($value, Constraint $constraint) {
try {
$response = $this->recaptchaManager->verify($value);
} catch (\Exception $e) {
$this->logger->error('reCAPTCHA failed: ' . $e->getMessage());
$this->context->buildViolation($constraint->message)
->atPath('recaptcha')
->addViolation();
}
}
Test Tokens
Use Google’s test tokens (0x3...) in dev to bypass validation:
andante_re_captcha:
secret: '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI' # Test secret
Symfony Profiler
Check the AndanteReCaptchaBundle tab in the profiler for validation stats and errors.
Custom Validation Logic Replace the default validator by binding your own service:
services:
App\Validator\CustomRecaptchaValidator:
tags: [validator.constraint_validator]
arguments: ['@andante_re_captcha.manager']
Then override the form type’s constraints:
$builder->add('recaptcha', ReCaptchaType::class, [
'constraints' => [new CustomRecaptchaConstraint()],
]);
Async Verification Offload verification to a queue (e.g., Symfony Messenger) for performance:
// src/Message/VerifyRecaptchaMessage.php
class VerifyRecaptchaMessage {
public function __construct(public string $token) {}
}
// In your form handler
$this->messageBus->dispatch(new VerifyRecaptchaMessage($form->get('recaptcha')->getData()));
Multi-Language Support Localize error messages by extending the constraint:
class LocalizedRecaptchaConstraint extends Constraint {
public $message = 'recaptcha.error'; // Translatable key
}
How can I help you explore Laravel packages today?