azine/emailupdateconfirmation-bundle
Install the Bundle
composer require azine/emailupdateconfirmation-bundle
Add to config/bundles.php (Symfony 4+):
return [
// ...
Azine\EmailUpdateConfirmationBundle\AzineEmailUpdateConfirmationBundle::class => ['all' => true],
];
Enable & Configure
Add to config/packages/azine_email_update_confirmation.yaml:
azine_email_update_confirmation:
enabled: true
redirect_route: fos_user_profile_show
Register Routes
Import in config/routes.yaml:
azine_email_update_confirmation:
resource: "@AzineEmailUpdateConfirmationBundle/Resources/config/routing.yml"
First Use Case
Extend User entity to add pendingEmail and emailConfirmedAt fields (see FOSUserBundle docs).
Example migration:
// src/Migrations/VersionYYYYMMDDHHMMSS.php
public function up(Schema $schema)
{
$table = $schema->getTable('fos_user_user');
$table->addColumn('pending_email', 'string', ['length' => 255, 'notnull' => false]);
$table->addColumn('email_confirmed_at', 'datetime', ['notnull' => false]);
}
Email Update Trigger
Override FOSUserBundle's UserManager to hook into email updates:
// src/EventListener/UserEmailUpdateListener.php
use Azine\EmailUpdateConfirmationBundle\Event\EmailUpdateEvent;
class UserEmailUpdateListener
{
public function onEmailUpdate(EmailUpdateEvent $event)
{
$user = $event->getUser();
$user->setPendingEmail($user->getEmail());
$user->setEmail($event->getNewEmail());
$user->setEmailConfirmedAt(null);
$user->getManager()->flush();
}
}
Register in services.yaml:
services:
App\EventListener\UserEmailUpdateListener:
tags:
- { name: kernel.event_listener, event: fos_user.email_update, method: onEmailUpdate }
Confirmation Flow
pending_email stored, old email ignored.azine.email_update.mailer service).emailConfirmedAt updated, pending_email cleared.Template Customization Override the default Twig template:
# config/packages/azine_email_update_confirmation.yaml
azine_email_update_confirmation:
email_template: '@App/Email/email_update_confirmation.html.twig'
Extend the base template (@AzineEmailUpdateConfirmation/Email/email_update_confirmation.txt.twig).
Form Integration
Extend FOSUserBundle's ChangeEmailFormType to validate pending emails:
// src/Form/Extension/EmailUpdateExtension.php
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
class EmailUpdateExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('pendingEmail', HiddenType::class);
}
}
Register as a form type extension in services.yaml.
Database Schema Mismatch
pending_email and email_confirmed_at fields exist in your user table.enabled: false during transition).Route Conflicts
/confirm-email-update/{token} by default. Verify no conflicts with existing routes.Mailer Service Dependency
azine.email_update.mailer to be defined. Configure it in services.yaml:
services:
azine.email_update.mailer:
class: Symfony\Bridge\Twig\Mime\TemplatedEmail
arguments:
- '@twig'
- '@mailer'
Token Expiry
ConfirmationController to add expiry logic if needed.Check Events
Enable debug for the fos_user.email_update event:
# config/packages/dev/monolog.yaml
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
Then filter logs for EmailUpdateEvent.
Token Validation If confirmation links fail, dump the token generation logic:
// src/EventListener/DebugTokenListener.php
use Azine\EmailUpdateConfirmationBundle\Event\EmailUpdateSentEvent;
class DebugTokenListener
{
public function onEmailUpdateSent(EmailUpdateSentEvent $event)
{
dump($event->getToken());
}
}
Configuration Overrides
Use dump(config('azine_email_update_confirmation')) to verify settings are loaded correctly.
Custom Token Generation
Override the TokenGenerator service:
services:
azine.email_update.token_generator:
class: App\Security\CustomTokenGenerator
arguments: ['@security.token_storage']
Implement generateToken() to use a custom strategy (e.g., UUID instead of hash).
Async Email Sending Decouple email sending by replacing the mailer service with a queue-based solution:
services:
azine.email_update.mailer:
class: App\Messenger\EmailMessage
arguments: ['@twig', '@messenger']
Multi-Factor Confirmation Extend the confirmation flow to require additional steps (e.g., SMS verification):
// src/EventSubscriber/EmailUpdateSubscriber.php
use Azine\EmailUpdateConfirmationBundle\Event\EmailConfirmedEvent;
class EmailUpdateSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
EmailConfirmedEvent::NAME => 'onEmailConfirmed',
];
}
public function onEmailConfirmed(EmailConfirmedEvent $event)
{
// Trigger SMS verification or other logic
}
}
Bulk Email Updates Disable confirmation for admin-initiated bulk updates:
// src/Command/BulkEmailUpdateCommand.php
use Azine\EmailUpdateConfirmationBundle\AzineEmailUpdateConfirmationBundle;
class BulkEmailUpdateCommand extends ContainerAwareCommand
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$bundle = $this->getContainer()->get('azine.email_update_confirmation');
$bundle->setEnabled(false); // Temporarily disable
// ... bulk update logic ...
$bundle->setEnabled(true);
}
}
How can I help you explore Laravel packages today?