Extending the Controller
Create your own controller that extends the package controller:
<?php
namespace App\Http\Controllers;
use MilenMk\LaravelEmailChangeConfirmation\Controllers\EmailChangeController as BaseController;
use MilenMk\LaravelEmailChangeConfirmation\Models\EmailChange;
use Illuminate\Http\RedirectResponse;
class CustomEmailChangeController extends BaseController
{
protected function handleSuccessfulConfirmation(EmailChange $emailChange): RedirectResponse
{
// Custom logic after successful confirmation
// Log the email change
\Log::info('Email changed', [
'user_id' => $emailChange->user_id,
'old_email' => $emailChange->current_email,
'new_email' => $emailChange->new_email,
]);
// Send custom notification
$emailChange->user->notify(new \App\Notifications\EmailChangedNotification());
return parent::handleSuccessfulConfirmation($emailChange);
}
protected function getSuccessRedirect(): RedirectResponse
{
// Custom redirect logic
return redirect()->route('profile.settings');
}
}
Update your configuration:
// config/email-change-confirmation.php
'email_change_controller' => App\Http\Controllers\CustomEmailChangeController::class,
Configuring Redirects
You can configure where users are redirected after email change actions:
// config/email-change-confirmation.php
'redirect_after_confirm' => 'dashboard', // After confirming email change
'redirect_after_deny' => 'profile.edit', // After denying email change
'redirect_after_cancel' => 'profile.edit', // After canceling pending change
If no redirect route is configured, the package will try common routes like dashboard
, home
, profile.show
, or
profile
, and fall back to the root URL (/
).
For the cancel action specifically, if no redirect is configured, it will use back()
to return to the previous page.
Custom Notification
Create your own notification class:
<?php
namespace App\Notifications;
use MilenMk\LaravelEmailChangeConfirmation\Notifications\EmailChangeConfirmation as BaseNotification;
use Illuminate\Notifications\Messages\MailMessage;
class CustomEmailChangeNotification extends BaseNotification
{
protected function buildMailMessage(string $confirmUrl, string $denyUrl): MailMessage
{
return (new MailMessage())
->subject('Confirm Your Email Change - ' . config('app.name'))
->greeting('Hello ' . $this->username . '!')
->line('We received a request to change your email address.')
->line('New email address: **' . $this->newEmail . '**')
->action('Confirm Email Change', $confirmUrl)
->line('If you did not request this change, please click the deny button below.')
->action('Deny Request', $denyUrl)
->line(
'This link will expire in ' .
config('email-change-confirmation.confirmation_email_expire_minutes') .
' minutes.',
);
}
}
Custom Service
Extend the service for custom business logic:
<?php
namespace App\Services;
use MilenMk\LaravelEmailChangeConfirmation\Services\EmailChangeService as BaseService;
use Illuminate\Database\Eloquent\Model;
class CustomEmailChangeService extends BaseService
{
public function requestEmailChange(Model $user, string $newEmail): EmailChange
{
// Custom validation
if ($this->isEmailBlacklisted($newEmail)) {
throw new \Exception('This email domain is not allowed.');
}
// Custom rate limiting
if ($this->hasRecentEmailChangeAttempt($user)) {
throw new \Exception('Please wait before requesting another email change.');
}
return parent::requestEmailChange($user, $newEmail);
}
private function isEmailBlacklisted(string $email): bool
{
// Your custom logic
return false;
}
private function hasRecentEmailChangeAttempt(Model $user): bool
{
// Your custom logic
return false;
}
}
Working with Different Laravel Setups
Laravel Breeze
Works out of the box. Just add the trait to your User model.
Laravel Jetstream
Works with both Livewire and Inertia stacks. For Inertia, you'll need to handle the frontend notifications manually.
Laravel Fortify
The package integrates seamlessly with Fortify's profile update actions.
Custom Applications
The package is designed to work with any Laravel application structure. Use manual integration if auto-detection doesn't
work for your setup.