php
51 lines · 6 steps
Email confirmation with signed URLs in Laravel
A controller that verifies emails through tamper-proof signed links and resends fresh ones on demand.
Explained by
highlit
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Models\User;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Http\Request;
8use Illuminate\Support\Facades\URL;
9
10class EmailConfirmationController extends Controller
11{
12 public function __construct()
13 {
14 $this->middleware('signed')->only('confirm');
15 $this->middleware('auth')->only('resend');
16 }
17
18 public function confirm(Request $request, User $user): RedirectResponse
19 {
20 if ($user->hasVerifiedEmail()) {
21 return redirect()->route('dashboard')
22 ->with('status', 'Your email address is already confirmed.');
23 }
24
25 $user->markEmailAsVerified();
26
27 event(new \Illuminate\Auth\Events\Verified($user));
28
29 return redirect()->route('dashboard')
30 ->with('status', 'Thanks! Your email address has been confirmed.');
31 }
32
33 public function resend(Request $request): RedirectResponse
34 {
35 $user = $request->user();
36
37 if ($user->hasVerifiedEmail()) {
38 return back()->with('status', 'Your email is already confirmed.');
39 }
40
41 $signedUrl = URL::temporarySignedRoute(
42 'email.confirm',
43 now()->addMinutes(60),
44 ['user' => $user->getKey()]
45 );
46
47 $user->notify(new \App\Notifications\ConfirmEmailAddress($signedUrl));
48
49 return back()->with('status', 'A fresh confirmation link has been sent.');
50 }
51}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Signed URLs let you trust a link's parameters without storing per-user tokens in the database.
- 2Guard every state change with an idempotency check so replaying a link causes no harm.
- 3Firing a domain event on verification decouples the side effects from the controller.
Related explainers
go
package middleware import ( "net/http"
Localized validation errors in Gin
middleware
internationalization
validation
Intermediate
8 steps
php
<?php namespace App\RateLimiting;
Sliding-window rate limiting with Redis sorted sets
rate-limiting
redis
sorted-sets
Advanced
8 steps
php
<?php namespace App\Models\Concerns;
How an Auditable trait logs Eloquent changes in Laravel
traits
model-events
polymorphic-relations
Intermediate
8 steps
php
<?php namespace App\Http\Controllers;
Server-Sent Events in Laravel
server-sent-events
streaming
long-polling
Advanced
9 steps
javascript
import { NextResponse } from 'next/server'; const locales = ['en', 'fr', 'de', 'es']; const defaultLocale = 'en';
Locale routing with Next.js middleware
middleware
i18n
content-negotiation
Intermediate
10 steps
go
package middleware import ( "crypto/sha256"
Deduplicating concurrent requests in Gin
singleflight
request-coalescing
middleware
Advanced
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/email-confirmation-with-signed-urls-in-laravel-explained-php-6e25/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.