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

Laravel Turnstile Laravel Package

coderflex/laravel-turnstile

Add Cloudflare Turnstile CAPTCHA to Laravel with minimal setup. Includes config publishing, env-based site/secret keys, validation integration, and customizable/translatable error messages for protecting forms and endpoints from bots.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Installation:

    composer require coderflex/laravel-turnstile
    php artisan vendor:publish --tag="turnstile-config"
    

    Add your Cloudflare Turnstile keys to .env:

    TURNSTILE_SITE_KEY=your_site_key
    TURNSTILE_SECRET_KEY=your_secret_key
    
  2. First Use Case: Add the Turnstile widget to a Blade form:

    <x-turnstile-widget theme="dark" language="en-US" />
    

    Validate the response in your controller:

    use Coderflex\LaravelTurnstile\Facades\LaravelTurnstile;
    
    public function store(Request $request) {
        $response = LaravelTurnstile::validate();
        if (!$response['success']) {
            return back()->withErrors(['captcha' => 'Invalid CAPTCHA']);
        }
    }
    

Implementation Patterns

1. Frontend Integration

  • Widget Placement: Use the <x-turnstile-widget /> component in forms where bot protection is needed (registration, contact forms, etc.).
  • Customization: Pass Turnstile’s client-side options as attributes:
    <x-turnstile-widget
        theme="auto"
        size="compact"
        language="es"
        callback="handleTurnstileSubmit"
    />
    
  • Error Handling: Display validation errors alongside the widget:
    @error('cf-turnstile-response')
        <p class="text-red-500">{{ $message }}</p>
    @enderror
    

2. Backend Validation

  • Facade Method: Use LaravelTurnstile::validate() to check the response in controllers:
    $result = LaravelTurnstile::validate($request->input('cf-turnstile-response'));
    if (!$result['success']) {
        return back()->withInput()->withErrors(['captcha' => trans('turnstile.error_messages.turnstile_check_message')]);
    }
    
  • Custom Validation Rule: Integrate with Laravel’s validation pipeline:
    use Coderflex\LaravelTurnstile\Rules\TurnstileCheck;
    
    $request->validate([
        'cf-turnstile-response' => ['required', new TurnstileCheck()],
    ]);
    

3. API/Non-Form Usage

  • Manual Validation: Validate Turnstile responses outside form submissions (e.g., API endpoints):
    $response = LaravelTurnstile::validate($request->input('turnstile_token'));
    if (!$response['success']) {
        return response()->json(['error' => 'Invalid CAPTCHA'], 400);
    }
    

4. Testing

  • Dummy Keys: Use Cloudflare’s test keys in .env for local development:
    TURNSTILE_SITE_KEY=0x4AAAAAAAAAAAAAAAAAAAAAGGeSlP9
    TURNSTILE_SECRET_KEY=0x4AAAAAAAAAAAAAAAAAAAAAGGeSlQ
    
  • Unit Tests: Mock the facade for testing:
    $this->mock(LaravelTurnstile::class)->shouldReceive('validate')
        ->once()
        ->andReturn(['success' => true]);
    

Gotchas and Tips

Pitfalls

  1. Missing .env Keys:

    • If TURNSTILE_SITE_KEY or TURNSTILE_SECRET_KEY are missing, the package throws a RuntimeException. Always validate these in .env before use.
    • Fix: Add a check in your controller:
      if (config('turnstile.turnstile_secret_key') === null) {
          throw new \RuntimeException('Turnstile secret key not configured.');
      }
      
  2. Incorrect Field Name:

    • The package expects the Turnstile response in the field cf-turnstile-response by default. If you rename this in your form, the validation will fail.
    • Fix: Pass the custom field name to the facade:
      LaravelTurnstile::validate($request->input('custom_turnstile_field'));
      
  3. Rate Limiting:

    • Cloudflare Turnstile has rate limits. Exceeding these may return 429 errors.
    • Fix: Implement retry logic or cache responses for high-traffic forms.
  4. JavaScript Dependency:

    • The Turnstile widget requires the Cloudflare script (https://challenges.cloudflare.com/turnstile/v0/api.js). Ensure it’s loaded before the widget renders.
    • Fix: Add the script to your layout or use the published views:
      @include('turnstile::script')
      

Debugging Tips

  • Enable Logging: Add debug logs to config/turnstile.php to trace validation issues:

    'debug' => env('TURNSTILE_DEBUG', false),
    

    Then check Laravel logs for Turnstile-related entries.

  • Raw API Response: Inspect the raw response from Cloudflare for debugging:

    $response = LaravelTurnstile::validate();
    \Log::debug('Turnstile raw response:', $response);
    

Extension Points

  1. Custom Error Messages: Override the default error message in config/turnstile.php:

    'error_messages' => [
        'turnstile_check_message' => 'You must complete the verification process.',
    ],
    
  2. Extend Validation Logic: Subclass the TurnstileCheck rule to add custom logic:

    use Coderflex\LaravelTurnstile\Rules\TurnstileCheck as BaseTurnstileCheck;
    
    class CustomTurnstileCheck extends BaseTurnstileCheck {
        public function passes($attribute, $value) {
            $result = parent::passes($attribute, $value);
            // Add custom logic here
            return $result;
        }
    }
    
  3. Dynamic Widget Configuration: Use Blade directives to dynamically set widget attributes:

    @turnstileWidget(['theme' => 'dark', 'language' => app()->getLocale()])
    

Performance Considerations

  • Caching: Cache the Turnstile widget HTML if used across multiple pages to reduce render time.
  • Lazy Loading: Load the Turnstile script asynchronously to avoid blocking page rendering:
    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity