Laravel
EU CAPTCHA integrates with Laravel via the myra-security-gmbh/eu-captcha PHP package.
Installation
composer require myra-security-gmbh/eu-captcha
Configuration
Store credentials in .env and expose them through config/services.php — the Laravel convention for third-party credentials:
.env
EUCAPTCHA_SITE_KEY=YOUR_SITEKEY
EUCAPTCHA_SECRET_KEY=YOUR_SECRET
config/services.php
'eucaptcha' => [
'sitekey' => env('EUCAPTCHA_SITE_KEY'),
'secret' => env('EUCAPTCHA_SECRET_KEY'),
],
Controller
<?php
namespace App\Http\Controllers;
use Myrasec\EuCaptcha;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
class ContactController extends Controller
{
public function submit(Request $request): RedirectResponse
{
$captcha = new EuCaptcha(
sitekey: config('services.eucaptcha.sitekey'),
secret: config('services.eucaptcha.secret'),
);
$result = $captcha->validate(
$request->input('eu-captcha-response'),
$request->ip(),
);
if (!$result->success()) {
return back()->withErrors(['captcha' => 'CAPTCHA verification failed.']);
}
// process the form...
return redirect()->route('contact.success');
}
}
$request->ip() respects Laravel's trusted proxy configuration (set via App\Http\Middleware\TrustProxies or the trustedproxy config), so the real visitor IP is forwarded correctly when running behind a load balancer or CDN.
Form Request
For reusable validation across multiple controllers, add the CAPTCHA check to a dedicated FormRequest:
<?php
namespace App\Http\Requests;
use Myrasec\EuCaptcha;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
class ContactRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email'],
'message' => ['required', 'string'],
];
}
protected function withValidator(Validator $validator): void
{
$validator->after(function (Validator $validator) {
$captcha = new EuCaptcha(
sitekey: config('services.eucaptcha.sitekey'),
secret: config('services.eucaptcha.secret'),
);
$result = $captcha->validate(
$this->input('eu-captcha-response'),
$this->ip(),
);
if (!$result->success()) {
$validator->errors()->add('captcha', 'CAPTCHA verification failed.');
}
});
}
}
Inject ContactRequest instead of Request in your controller method — Laravel resolves and validates it automatically before the method body runs:
public function submit(ContactRequest $request): RedirectResponse
{
// validation and CAPTCHA check already passed
// process the form...
return redirect()->route('contact.success');
}