Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Recaptcha Bundle Laravel Package

acrobat/recaptcha-bundle

Symfony2 form integration for Google reCAPTCHA. Install via Composer, register the bundle, and configure your public/private keys in config.yml. Supports disabling per environment and optional Ajax loading, helping protect forms from spam and bots.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require acrobat/recaptcha-bundle:~2.0
    

    Enable the bundle in config/bundles.php:

    Acrobat\RecaptchaBundle\AcrobatRecaptchaBundle::class => ['all' => true],
    
  2. Configuration: Add your reCAPTCHA keys to config/packages/acrobat_recaptcha.yaml:

    acrobat_recaptcha:
        site_key: 'YOUR_SITE_KEY'
        secret_key: 'YOUR_SECRET_KEY'
        version: 'v2' # or 'v1' if using legacy
    
  3. First Use Case: Add reCAPTCHA to a form in FormType:

    use Acrobat\RecaptchaBundle\Form\Type\RecaptchaType;
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('recaptcha', RecaptchaType::class);
    }
    

    Render it in your template:

    {{ form_row(form.recaptcha) }}
    

Implementation Patterns

Common Workflows

  1. Form Integration:

    • Use RecaptchaType in any Symfony form (e.g., contact forms, registration).
    • Customize validation by overriding the RecaptchaValidator in a service:
      # config/services.yaml
      Acrobat\RecaptchaBundle\Validator\RecaptchaValidator:
          arguments:
              $client: '@acrobat_recaptcha.client'
              $version: '%acrobat_recaptcha.version%'
      
  2. Dynamic Key Handling:

    • Override keys per environment or per form:
      # config/packages/dev/acrobat_recaptcha.yaml
      acrobat_recaptcha:
          site_key: 'DEV_SITE_KEY'
          secret_key: 'DEV_SECRET_KEY'
      
  3. API Client Customization:

    • Extend the default RecaptchaClient to add logging or retry logic:
      class CustomRecaptchaClient extends RecaptchaClient
      {
          public function verify($response, $remoteIp)
          {
              // Custom logic (e.g., retry on failure)
              return parent::verify($response, $remoteIp);
          }
      }
      
      Register it in services.yaml:
      Acrobat\RecaptchaBundle\Client\RecaptchaClient: '@custom_recaptcha.client'
      
  4. Twig Integration:

    • Access reCAPTCHA settings in Twig:
      {% set recaptcha = app.container.get('acrobat_recaptcha') %}
      {{ recaptcha.siteKey }}
      
  5. Async Validation:

    • Use Symfony’s Constraint system for async validation (e.g., with Messenger):
      use Acrobat\RecaptchaBundle\Validator\Constraints\Recaptcha;
      
      #[Recaptcha()]
      public $recaptchaResponse;
      

Gotchas and Tips

Pitfalls

  1. Deprecated Bundle:

    • The bundle is archived (last release in 2014) and lacks support for Symfony 5/6 or reCAPTCHA v3.
    • Workaround: Fork the repo and update dependencies (e.g., symfony/form, guzzlehttp/guzzle) manually.
  2. Validation Errors:

    • If validation fails silently, check:
      • The secret_key is correct in config.
      • The response field name matches the form (recaptcha by default).
      • Network requests to google.com/recaptcha are not blocked (e.g., by firewall).
  3. CSRF Token Conflicts:

    • Ensure the form has {{ form_rest() }} or {{ form_csrf_token() }} to avoid token mismatches.
  4. Legacy reCAPTCHA v1:

    • v1 is deprecated by Google. Use v2 (default) or migrate to a modern alternative like symfony/webpack-encore + custom JS.

Debugging Tips

  1. Log API Responses:

    • Override RecaptchaClient to log raw responses:
      public function verify($response, $remoteIp)
      {
          $this->logger->debug('reCAPTCHA API Response:', ['response' => $response]);
          return parent::verify($response, $remoteIp);
      }
      
  2. Test Locally:

    • Use Google’s test keys (6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI) to bypass rate limits during development.
  3. Check Headers:

    • Verify the X-Forwarded-For header is passed correctly if behind a proxy:
      $remoteIp = $request->getClientIp(); // Use this instead of default
      

Extension Points

  1. Custom Validation Logic:

    • Extend the RecaptchaValidator to add score thresholds (e.g., for v3):
      public function validate($value, Constraint $constraint)
      {
          $result = $this->client->verify($value, $this->requestStack->getCurrentRequest()->getClientIp());
          if ($result->isSuccess() && $result->getScore() < 0.5) {
              $this->context->buildViolation($constraint->message)
                  ->addViolation();
          }
      }
      
  2. Multi-Language Support:

    • Override the Twig template (Resources/views/Recaptcha/recaptcha.html.twig) to support non-English labels:
      <div class="g-recaptcha" data-sitekey="{{ recaptcha.siteKey }}" data-callback="onSubmit" data-language="{{ app.request.get('_locale') }}"></div>
      
  3. Rate Limiting:

    • Implement a decorator for RecaptchaClient to cache responses and avoid hitting Google’s limits:
      class CachingRecaptchaClient implements RecaptchaClientInterface
      {
          private $decorated;
          private $cache;
      
          public function verify($response, $remoteIp)
          {
              $cacheKey = md5($response . $remoteIp);
              if ($this->cache->has($cacheKey)) {
                  return $this->cache->get($cacheKey);
              }
              $result = $this->decorated->verify($response, $remoteIp);
              $this->cache->set($cacheKey, $result, 3600); // Cache for 1 hour
              return $result;
          }
      }
      
  4. Alternative Providers:

    • Replace RecaptchaClient with a service for hCaptcha or other providers:
      class HCaptchaClient implements RecaptchaClientInterface
      {
          public function verify($response, $remoteIp)
          {
              // Call hCaptcha API instead
          }
      }
      

```markdown
### Laravel-Specific Adaptations
While this bundle is for Symfony, here’s how a Laravel developer might adapt it conceptually:

1. **Service Provider**:
   - Register the bundle’s logic in a Laravel service provider:
     ```php
     public function register()
     {
         $this->app->singleton('recaptcha', function ($app) {
             return new \Acrobat\RecaptchaBundle\Client\RecaptchaClient(
                 $app['config']['recaptcha.site_key'],
                 $app['config']['recaptcha.secret_key']
             );
         });
     }
     ```

2. **Form Request Validation**:
   - Use Laravel’s `FormRequest` to validate reCAPTCHA:
     ```php
     use Acrobat\RecaptchaBundle\Validator\Constraints\Recaptcha;

     public function rules()
     {
         return [
             'g-recaptcha-response' => ['required', new Recaptcha()]
         ];
     }
     ```

3. **Blade Integration**:
   - Render the reCAPTCHA widget in Blade:
     ```blade
     <div class="g-recaptcha"
         data-sitekey="{{ config('recaptcha.site_key') }}"
         data-callback="onSubmit">
     </div>
     ```

4. **Config File**:
   - Define keys in `.env`:
     ```
     RECAPTCHA_SITE_KEY=your_site_key
     RECAPTCHA_SECRET_KEY=your_secret_key
     ```
   - Load them in `config/recaptcha.php`:
     ```php
     'site_key' => env('RECAPTCHA_SITE_KEY'),
     'secret_key' => env('RECAPTCHA_SECRET_KEY'),
     ```

5. **Middleware for API Calls**:
   - Create middleware to verify reCAPTCHA on specific routes:
     ```php
     public function handle($request, Closure $next)
     {
         $response = $request->input('g-recaptcha-response');
         $client = app('recaptcha');
         $result = $client->verify($response, $request->ip());

         if (!$result->isSuccess()) {
             abort(403, 'Invalid reCAPTCHA');
         }
         return $next($request);
     }
     ```
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle