atournayre/confirmation-bundle
Symfony bundle that adds confirmation flows to your entities. Make entities confirmable via an interface/trait, generate and validate confirmation codes, and plug in custom delivery providers (email, SMS, etc.) configured through services and YAML routing.
Installation
composer require atournayre/confirmation-bundle
Register the bundle in config/bundles.php:
Atournayre\Bundle\ConfirmationBundle\AtournayreConfirmationBundle::class => ['all' => true],
Configure the Bundle
Create config/packages/atournayre_confirmation.yaml:
atournayre_confirmation:
providers:
# Example: email provider (replace with your custom provider)
email: App\Provider\EmailConfirmationProvider
Set Up Routing
Create config/routes/atournayre_confirmation.yaml:
atournayre_confirmation:
resource: "@AtournayreConfirmationBundle/Resources/config/routing.yaml"
Enable Services
Add the required services to config/services.yaml (refer to the README for full config).
First Use Case: Confirming a User Entity
ConfirmableInterface and use ConfirmableTrait in your entity (e.g., User):
use Atournayre\Bundle\ConfirmationBundle\Contracts\ConfirmableInterface;
use Atournayre\Bundle\ConfirmationBundle\Traits\ConfirmableTrait;
class User implements ConfirmableInterface
{
use ConfirmableTrait;
// ...
}
EmailConfirmationProvider) extending AbstractProvider:
namespace App\Provider;
use Atournayre\Bundle\ConfirmationBundle\Provider\AbstractProvider;
class EmailConfirmationProvider extends AbstractProvider
{
public function getRecipient(User $entity): string
{
return $entity->getEmail();
}
public function sendConfirmationCode(User $entity, string $code): void
{
// Send email with $code to $entity->getEmail()
}
}
config/packages/atournayre_confirmation.yaml:
atournayre_confirmation:
providers:
email: App\Provider\EmailConfirmationProvider
$generateConfirmationService = app()->make(\Atournayre\Bundle\ConfirmationBundle\Service\GenerateConfirmationService::class);
$generateConfirmationService($user);
app_confirmation_code_with_code or app_confirmation_code).User Registration Confirmation
$user = new User();
$user->setEmail($request->email);
$user->setPassword($request->password);
$user->save();
$generateConfirmationService($user); // Triggers email/SMS with confirmation code
User entity:
public function updateAfterConfirmation(): void
{
$this->setIsVerified(true);
$this->setVerifiedAt(new \DateTime());
}
Password Reset Confirmation
$resetToken = new ResetPasswordToken();
$resetToken->setUser($user);
$resetToken->setToken($generatedToken);
$resetToken->save();
$generateConfirmationService($resetToken);
Multi-Channel Confirmation (Email + SMS)
config/packages/atournayre_confirmation.yaml:
atournayre_confirmation:
providers:
email: App\Provider\EmailConfirmationProvider
sms: App\Provider\SmsConfirmationProvider
class MultiChannelConfirmationProvider extends AbstractProvider
{
public function __construct(
private EmailConfirmationProvider $emailProvider,
private SmsConfirmationProvider $smsProvider
) {}
public function sendConfirmationCode(User $entity, string $code): void
{
$this->emailProvider->sendConfirmationCode($entity, $code);
$this->smsProvider->sendConfirmationCode($entity, $code);
}
}
Custom Confirmation Logic
updateAfterConfirmation() in the entity for custom logic:
public function updateAfterConfirmation(): void
{
$this->setStatus('active');
$this->setConfirmedAt(now());
// Trigger additional actions (e.g., send welcome email)
}
Testing Confirmations
GenerateConfirmationService in tests:
$mockProvider = $this->createMock(EmailConfirmationProvider::class);
$mockProvider->method('sendConfirmationCode')->willReturn(true);
$container = new Container();
$container->set('App\Provider\EmailConfirmationProvider', $mockProvider);
$service = new GenerateConfirmationService($container);
$service($user); // Will use the mocked provider
Leverage Symfony’s Twig Templates
Override default templates (e.g., confirmation emails) by copying them from:
vendor/atournayre/confirmation-bundle/src/Resources/views/ to templates/atournayre_confirmation/.
Use Events for Extensibility
Listen for confirmation events (e.g., ConfirmationGeneratedEvent) to add side effects:
use Atournayre\Bundle\ConfirmationBundle\Event\ConfirmationGeneratedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ConfirmationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
ConfirmationGeneratedEvent::class => 'onConfirmationGenerated',
];
}
public function onConfirmationGenerated(ConfirmationGeneratedEvent $event): void
{
// Log or trigger analytics when a confirmation is generated
}
}
Rate Limiting Implement rate limiting in your provider to prevent abuse:
public function sendConfirmationCode(User $entity, string $code): void
{
if ($this->isRateLimited($entity)) {
throw new \RuntimeException('Too many confirmation requests.');
}
// Send confirmation
}
UUID Support
If your entity uses UUIDs, pass the UUID as the 3rd argument to GenerateConfirmationService:
$generateConfirmationService($user, null, $user->getUuid());
Provider Not Tagged
services.yaml:
services:
App\Provider\YourCustomProvider:
tags: ['atournayre.confirmation_bundle.tag.provider']
Overriding updateEntity()
updateEntity() in providers. Instead, use updateAfterConfirmation() in the entity.updateAfterConfirmation() method.Missing realTargetId for UUIDs
id and uuid.GenerateConfirmationService:
$generateConfirmationService($user, null, $user->getUuid());
Template Overrides Not Working
templates/atournayre_confirmation/ and named correctly (e.g., confirmation_email.html.twig).Confirmation Codes Not Expired
ConfirmationCodeRepository).Provider Not Public
GenerateConfirmationService fails with ServiceNotFoundException.public: true in services.yaml:
App\Provider\YourCustomProvider:
public: true
Check Logs for Provider Errors
storage/logs/laravel.log for provider-related errors (e.g., failed email/SMS sends).Verify Route Existence
php bin/console debug:router | grep confirmation
app_confirmation_code_with_code (direct link)app_confirmation_code (form submission)Inspect Confirmation Codes
confirmation_codes table to verify codes are generated:
php
How can I help you explore Laravel packages today?