gregwar/captcha
Generate CAPTCHA images in PHP with Gregwar CaptchaBuilder. Create, save, output, or embed captchas inline, retrieve and validate the phrase against user input, tweak distortion/background, and optionally build captchas resistant to OCR (with ocrad).
Installation:
composer require gregwar/captcha
Ensure your project meets the PHP 8.2+ requirement (Laravel 10+ compatible).
Basic Usage:
use Gregwar\Captcha\CaptchaBuilder;
$builder = new CaptchaBuilder();
$builder->build();
// Store the phrase in session for later validation
session(['captcha_phrase' => $builder->getPhrase()]);
// Output the CAPTCHA image
header('Content-Type: image/jpeg');
$builder->output();
Validation:
$userInput = request('captcha');
$isValid = $builder->testPhrase($userInput);
// OR compare with session:
$isValid = $builder->testPhrase(session('captcha_phrase'));
Inline HTML Usage (for forms):
<img src="<?php echo $builder->inline(); ?>" />
Protect a Login Form:
// In your controller:
$builder = new CaptchaBuilder();
session(['captcha_phrase' => $builder->getPhrase()]);
// In your blade view:
<img src="{{ $builder->inline() }}" alt="CAPTCHA" />
// Validation logic:
$request->validate([
'captcha' => ['required', function ($attribute, $value, $fail) {
$builder = new CaptchaBuilder();
if (!$builder->testPhrase($value)) {
$fail('The CAPTCHA code is incorrect.');
}
}],
]);
// In a middleware or service:
public function generateCaptcha()
{
$builder = new CaptchaBuilder();
$builder->build();
session(['captcha_phrase' => $builder->getPhrase()]);
return $builder;
}
// In AppServiceProvider
$this->app->singleton(CaptchaBuilder::class, function () {
return new CaptchaBuilder();
});
// In a FormRequest or controller:
$builder = app(CaptchaBuilder::class);
if (!$builder->testPhrase($request->captcha)) {
return back()->withErrors(['captcha' => 'Invalid CAPTCHA.']);
}
$builder = new CaptchaBuilder();
$builder
->setMaxBehindLines(3)
->setMaxFrontLines(2)
->setScatterEffect(true)
->buildAgainstOCR(); // For high-security forms
buildAgainstOCR() for forms where bots are likely (e.g., contact forms).
$builder->buildAgainstOCR(200, 50); // Wider and taller for OCR resistance
// In a test:
$builder = $this->createMock(CaptchaBuilder::class);
$builder->method('testPhrase')->willReturn(true);
$this->app->instance(CaptchaBuilder::class, $builder);
Form Requests: Centralize validation logic in a FormRequest class.
public function rules()
{
return [
'captcha' => ['required', 'string', new CaptchaRule],
];
}
class CaptchaRule implements Rule
{
public function passes($attribute, $value)
{
return app(CaptchaBuilder::class)->testPhrase($value);
}
}
Caching: Cache the CAPTCHA image for 5 minutes to reduce generation overhead.
$key = 'captcha_' . uniqid();
Cache::put($key, $builder->get(), now()->addMinutes(5));
return $key; // Return as image URL
Filament Admin: Use the Filament extension for admin panel protection.
use MarcoGermani87\FilamentCaptcha\FilamentCaptcha;
FilamentCaptcha::make()
->maxAttempts(3)
->build();
setIgnoreAllEffects(true)) for low-security forms to improve rendering speed.throttle middleware to prevent brute-force attacks.
Route::middleware(['throttle:5,1'])->group(function () {
// CAPTCHA-protected routes
});
Session Management:
session()->forget('captcha_phrase');
OCR Detection Overhead:
buildAgainstOCR() can be slow if ocrad is not optimized or if the system lacks shell_exec support.try {
$builder->buildAgainstOCR();
} catch (\Exception $e) {
$builder->build(200, 50)->setScatterEffect(true);
}
Font Paths:
vendor/gregwar/captcha/src/Gregwar/Captcha/fonts/.Image Output Type:
setImageType() to png or gif may break existing clients expecting JPEG.jpeg unless explicitly needed:
$builder->setImageType('jpeg');
PHP Version Mismatch:
v1.3.0).CAPTCHA Not Displaying:
header('Content-Type: image/jpeg') is set before output().$builder->save(storage_path('app/captcha.jpg'));
Validation Failing:
A vs a). CAPTCHAs are case-sensitive by default.\Log::debug('Stored:', ['phrase' => session('captcha_phrase')]);
\Log::debug('Input:', ['phrase' => $request->captcha]);
Performance Bottlenecks:
setIgnoreAllEffects(true) to disable all effects and measure rendering time.buildAgainstOCR).Custom Phrases:
PhraseBuilder for controlled character sets (e.g., numeric-only CAPTCHAs):
$phraseBuilder = new PhraseBuilder(6, '0123456789');
$builder = new CaptchaBuilder(null, $phraseBuilder);
Background Customization:
setBackgroundImages() for themed CAPTCHAs (e.g., match your brand):
$builder->setBackgroundImages([
public_path('images/bg1.png'),
public_path('images/bg2.png'),
]);
Laravel View Composers:
// In AppServiceProvider
View::composer('*', function ($view) {
$view->with('captcha', app(CaptchaBuilder::
How can I help you explore Laravel packages today?