Manually verifying created users when using Laravel Email Verification

Laravel 5.7 ships with bundled Email Verification. This is great if you want to make sure a user’s email address is valid (or at least that the user can access it) before allowing them access.

Problem:
What if you want to manually verify a user without sending them an email address? For example you might want to add or import a load of existing ‘known-good’ users to a migrated app. Or you might be creating Admin or System users that don’t really have accessible email addresses. There could be many reasons.

At present as soon you register a user, the sendEmailVerificationNotification method is called. There’s a good breakdown of how this works in this Stack Overflow answer. If a user is manually created, then when they try to log in they’ll still see the “Verify your email address” message:

Laravel's email verification message

Solutions:
Whether a user has verified their email address or not is indicated by a timestamp in the email_verified_at column of the User table¹. If this column is set to a valid timestamp upon user creation, the user will be ‘validated’ and no email will be sent. So… how can we set that timestamp? 

Option 1 – making `email_verified_at` fillable:
If you are creating a user manually, at the time of creation you could manually set the email_verified_at column to a valid timestamp. To do that email_verified_at could be added to the $fillable array in the model. For example in app/User.php:

protected $fillable = [
    'name', 'email', 'password', 'email_verified_at',
];

…and then the value could be set as part of the Create method used to create the user. e.g:

$user = User::create([
    'name' => 'Mr Benn',
    'email' => 'user@example.com',
    'password' => Hash::make('password'),
    'email_verified_at' => now() //Carbon instance
]);

This is a bit cheesy though, we can do this without changing what’s fillable.

Option 2 – using `forceCreate()`:
If you want to leave the $fillable array alone, forceCreate() can be used like so:

$user = User::forceCreate([
    'name' => 'Mr Benn',
    'email' => 'user@example.com',
    'password' => Hash::make('password'),
    'email_verified_at' => now() //Carbon instance
]);

Option 3 – use the `markEmailAsVerified()` method:
If the user needs to be verified after creation then the markEmailAsVerified() could be used. Here are two examples:

$user = User::create([
    'name' => 'Mr Benn',
    'email' => 'user@example.com',
    'password' => Hash::make('password')
]);

$user->markEmailAsVerified();
$user = User::where('email', $email)->first();
$user->markEmailAsVerified();

Any questions to corrections? Please leave a comment. If this was useful, I’d love to know with a click: Nope, not helpful...Yep, more useful than not! (No Ratings Yet)
Loading...

Footnotes:
1. This apples to whichever Authenticatable user model/table you are using. If you don’t have this column, check over the setup info in the Email Verification docs.

Leave a Reply

Your e-mail address will not be published. Required fields are marked *