Laravel ships with a fairly nice default password broker. It creates an auto-expiring reset token, associates that with the user, and sends an email to the user all in one nice fairly modular system. But, there's a problem…
How do you add dynamic data to your reset view.
By default, Laravel will pass through the requesting user and the new token that was created. But, there are times where you need more.
Looking around the usual haunts of Stack Exchange, and Laravel.io: most people recommend firing the underlying token logic yourself, then calling mail send.
It's a bit of smell to have to replicate half of the logic that is available from PasswordBroker.sendResetLink
.
Or they say to create a view composer, on the fly and I'm not a huge fan of that either (view composers should be available for all logic not just a single flow).
Instead, I wanted a way to be able to add data to my reset email without ripping out the guts of the rest of Laravel's existing logic.
At this point, you might be asking "why would I want to do this"? So consider the following system.
An app you are building has a closed registration process (only admins can create users). You don't want admins to set user passwords because they will most likely never be reset to something else.
Instead, you fill in the password with a random string and hash that (or even better a random string that isn't a valid hash so it never matches if someone tried to brute force guess passwords). Then you send the user a reset email to set the password on their new account.
This flow is great because you use existing tested logic to bring a new user into your system instead of having to maintain a password reminder AND a confirmation setup.
But, for most users, they'll be more than a little confused when they see an email telling them to reset a password on a site they've never been to or created an account for.
So, if we want to use the reset system and keep the nice syntax of PasswordBroker.sendResetLink
.
The magic comes from the optional callback that is accepted as the second argument to sendResetLink
.
Usually you would use this to change the replyTo
or subject for a Swift Mail Message.
But, there's more going on under the hood.
The callback has access to the Swift_Message
instance that eventually is used to send the email.
And in the send
function in Laravel's Mailer
, this Swift_Message
instance is set to the message
variable in our template.
Most often, this is used to use the email's subject in the template.
But, we can do a lot more than this.
By setting undefined public properties on Swift_Message
in this callback, we can pass almost ANYTHING into our email template.
So, for the example above with creating a User with a random password, and sending an email, my code can look like this:
public function createWithRandomPassword($attributes = [])
{
$attributes['password'] = Hash::make(str_random());
$user = $this->user->create($attributes);
return $this->passwordBroker->sendResetLink($user->toArray(), function($message) {
$message->newUser = true;
});
}
And my template can grab that newUser
property:
@if ($message->newUser)
<h1>Welcome New user!</h1>
@endif
<p>Click here to reset your password: {{ url('password/reset/'.$token) }}</p>
Do you have any hacks in Laravel that you like? Share them in the comments below!
Are you a Laravel or Ember developer wanting to branch out and learn how to build awesome apps in Node and Express? Sign up for the newsletter at embergrep.com to learn more about my upcoming course "Express.js: Zero to Sixty"!