Installation:
composer require gregwar/captcha-bundle
(No manual registration needed if using Symfony Flex.)
First Use Case:
Add the CaptchaType to a form in your controller:
use Gregwar\CaptchaBundle\Type\CaptchaType;
$builder->add('captcha', CaptchaType::class);
This renders a CAPTCHA image + input field by default.
Where to Look First:
config/packages/gregwar_captcha.yaml (auto-generated if needed).as_url, add the bundle’s routes to config/routes.yaml:
gregwar_captcha_routing:
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
Basic Form Integration:
// Controller
$form = $this->createFormBuilder()
->add('name', TextType::class)
->add('captcha', CaptchaType::class, [
'length' => 6,
'reload' => true, // Adds a "refresh" link
])
->getForm();
length: Adjust CAPTCHA complexity (default: 5).reload: Adds a "refresh" link (useful for UX).disabled: Set to true in dev environments to skip validation.Dynamic Configuration:
Override defaults per form or globally in config/packages/gregwar_captcha.yaml:
gregwar_captcha:
width: 200
height: 60
charset: "abcdefghjkmnpqrstuvwxyz23456789" # Exclude ambiguous chars
distortion: false # Disable distortion for testing
Multi-CAPTCHA Forms:
Use session_key to isolate CAPTCHAs on the same page:
$builder->add('captcha1', CaptchaType::class, ['session_key' => 'form1_captcha']);
$builder->add('captcha2', CaptchaType::class, ['session_key' => 'form2_captcha']);
File-Based CAPTCHAs:
Enable as_file for IE6/7 compatibility or multi-server setups:
$builder->add('captcha', CaptchaType::class, [
'as_file' => true,
'image_folder' => 'custom_captcha_folder',
]);
web_path config (default: %kernel.project_dir%/public).URL-Based Generation:
For distributed systems, use as_url:
$builder->add('captcha', CaptchaType::class, [
'as_url' => true,
'whitelist_key' => 'custom_whitelist_key',
]);
/generate-captcha/{key} route is accessible.Validation: Handle validation in your controller:
if (!$form->isValid()) {
$errors = $form->getErrors(true);
if ($errors->has('captcha')) {
// Log or notify about CAPTCHA failure
}
}
Theming:
Customize the Twig template (templates/form/captcha_widget.html.twig):
{% block captcha_widget %}
<div class="captcha-container">
<img src="{{ captcha_code }}" alt="CAPTCHA" />
<input type="text" name="{{ form.vars.name }}" />
<a href="#" onclick="this.parentNode.querySelector('img').src='/generate-captcha?reload'; return false;">
Refresh
</a>
</div>
{% endblock %}
Session Key Conflicts:
session_key, the second CAPTCHA may overwrite the first.session_key for multi-CAPTCHA forms.File-Based CAPTCHA Cleanup:
gc_freq). Old files may linger if expiration is too high.use Gregwar\CaptchaBundle\Generator\CaptchaGenerator;
$generator = new CaptchaGenerator();
$generator->cleanup();
IE6/7 Compatibility:
as_file=false, as_url=false) may fail in IE6/7 due to XSS restrictions.as_file=true or as_url=true for legacy support.Distortion and Background Images:
background_images is set, ignore_all_effects must be true to avoid rendering artifacts.gregwar_captcha:
background_images: ["%kernel.project_dir%/path/to/image1.png", ...]
ignore_all_effects: true
Bypass Code Security:
bypass_code option is useful for testing but should never be used in production.null in production:
gregwar_captcha:
bypass_code: null
Routing Conflicts:
/generate-captcha/{key} route may conflict with existing routes.config/routes.yaml:
gregwar_captcha_routing:
resource: "@GregwarCaptchaBundle/Resources/config/routing/routing.yml"
prefix: /_captcha
Font Paths:
%kernel.project_dir%/public/fonts/captcha.ttf).font option:
$builder->add('captcha', CaptchaType::class, [
'font' => '%kernel.project_dir%/public/fonts/Roboto-Bold.ttf',
]);
Humanity Check:
humanity option skips CAPTCHAs after a correct submission, but does not reset on form errors.$request->getSession()->remove('captcha_humanity_check');
Check Session Storage:
captcha_<session_key>.dump($request->getSession()->all());
Validate Image Generation:
as_file mode.phpinfo()).background_images paths.Log Validation Errors:
invalid_message to include debug info:
gregwar_captcha:
invalid_message: "CAPTCHA failed. Expected: {{ expected }}, Got: {{ submitted }}"
Test Distortion:
distortion: false) to verify CAPTCHA readability:
gregwar_captcha:
distortion: false
Custom Validation: Override the validator in a form type:
use Symfony\Component\Validator\Constraints as Assert;
$builder->add('captcha', CaptchaType::class, [
'constraints' => [
new Assert\Callback(function ($value, ExecutionContextInterface $context) {
// Custom logic (e.g., check against a database)
}),
],
]);
Event Listeners:
Hook into CAPTCHA generation via Symfony events (e.g., kernel.request):
// src/EventListener/CaptchaListener.php
public function onKernelRequest(GetResponseEvent $event) {
if ($event->isMasterRequest()) {
$request = $event->getRequest();
if ($request->isXmlHttpRequest() && $request->get('_route') === 'generate_captcha') {
// Modify CAPTCHA behavior dynamically
}
}
}
Dynamic Configuration: Use a compiler pass to override settings at runtime:
// src/DependencyInjection/Compiler/CaptchaPass.php
public function process(ContainerBuilder $container) {
$definition = $container->findDefinition('gregwar_captcha.generator');
$definition->replaceArgument(0, [
'width' => $this->get
How can I help you explore Laravel packages today?