Laravel 5.3 How to show Username in Notifications Email
Asked Answered
P

3

8

I am trying to add the user's first name in the notification emails. At the moment, Laravel notification emails starts like:

Hello,

And I want to change it to:

Hello Donald,

Right now, I have a set-up like this. This example is for a Password Reset Notification email:

User Model:

public function sendPasswordResetNotification($token)
        {
            $this->notify(new PasswordReset($token));
        }

App\Notifications\PasswordReset:

class PasswordReset extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', 'https://laravel.com')
                    ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

Is the User Model automatically binded with the Notification Class? How can I add the username in the view?

Pratique answered 20/11, 2016 at 12:4 Comment(4)
now your email send without username?Misapprehension
yes. It starts with Hello! in the notification email which is the default. If I add $user->first_name or $first_name to the blade, it throws the undefined variable error. So I believe the user object needs to be sent from notification class?Pratique
did you create a mail class for that and a view?Virus
No. Since it is a notification, I have created the notification class PasswordReset .Pratique
M
9

Try this:

User Model:

public function sendPasswordResetNotification($token) {
    return $this->notify(new PasswordReset($token, $this->username));
}

App\Notifications\PasswordReset:

class PasswordReset extends Notification
{
    use Queueable;

    public $username;

    public function __construct($token, $username)
    {
        $this->username = $username;
    }

    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->greeting('Hello '.$this->username.',')
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', 'https://laravel.com')
                    ->line('Thank you for using our application!');
    }
}
Misapprehension answered 20/11, 2016 at 13:6 Comment(5)
That didnt work. I am getting the error: Argument 1 passed to App\Notifications\PasswordReset::__construct() must be an instance of App\Models\User, string given, called in /app/Models/User.php on line 65 and defined. This is because the $token is passed when calling this Notification class. So when I change to: public function __construct($token, User $user), I am now getting the error Argument 2 passed to App\Notifications\PasswordReset::__construct() must be an instance of App\Models\User, none given and defined. It is expecting the User Model to be passed when calling the class.Pratique
That is perfect. Exactly what I was after. This line did it for me return $this->notify(new PasswordReset($token, $this->username));. I didn't know I can easily send the user name from the override method in user model directly. Thank you so much!Pratique
@RimonKhan can you explain why this works in the context of the password reset workflow? I don't understand how the User instance is being instantiated or passed looking at the password reset code.Wobble
Oh sorry, never mind. $this->email worked for me because my User model did not have a username property. :)Wobble
$notifiable is already passed to toMail($notifiable). That's your user model.Appointive
K
41

The $notifiable variable passed to toMail() is User model.

Call to needed User model attribute, easy:

public function toMail($notifiable)
{
     return (new MailMessage)
        ->greeting('Hello '. $notifiable->username)
        ->line('The introduction to the notification.')
        ->action('Notification Action', 'https://laravel.com')
        ->line('Thank you for using our application!');
}
Kazbek answered 9/12, 2017 at 7:40 Comment(0)
M
9

Try this:

User Model:

public function sendPasswordResetNotification($token) {
    return $this->notify(new PasswordReset($token, $this->username));
}

App\Notifications\PasswordReset:

class PasswordReset extends Notification
{
    use Queueable;

    public $username;

    public function __construct($token, $username)
    {
        $this->username = $username;
    }

    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->greeting('Hello '.$this->username.',')
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', 'https://laravel.com')
                    ->line('Thank you for using our application!');
    }
}
Misapprehension answered 20/11, 2016 at 13:6 Comment(5)
That didnt work. I am getting the error: Argument 1 passed to App\Notifications\PasswordReset::__construct() must be an instance of App\Models\User, string given, called in /app/Models/User.php on line 65 and defined. This is because the $token is passed when calling this Notification class. So when I change to: public function __construct($token, User $user), I am now getting the error Argument 2 passed to App\Notifications\PasswordReset::__construct() must be an instance of App\Models\User, none given and defined. It is expecting the User Model to be passed when calling the class.Pratique
That is perfect. Exactly what I was after. This line did it for me return $this->notify(new PasswordReset($token, $this->username));. I didn't know I can easily send the user name from the override method in user model directly. Thank you so much!Pratique
@RimonKhan can you explain why this works in the context of the password reset workflow? I don't understand how the User instance is being instantiated or passed looking at the password reset code.Wobble
Oh sorry, never mind. $this->email worked for me because my User model did not have a username property. :)Wobble
$notifiable is already passed to toMail($notifiable). That's your user model.Appointive
T
2

You have to edit toMail function in App\Notifications\PasswordReset to set greeting as you want.

public function toMail($notifiable) {
     return (new MailMessage)
        ->greeting('Hello '. $this->username)
        ->line('The introduction to the notification.')
        ->action('Notification Action', 'https://laravel.com')
        ->line('Thank you for using our application!');
}

Update

To set $username, have to define a variable & setter method in App\Notifications\PasswordReset.

protected $username = null;

public function setName($name) {
    $this->username = $name;
}

When you initialize App\Notifications\PasswordReset, you can set the name.

In User model update the function as below.

public function sendPasswordResetNotification($token) {
    $resetNotification = new ResetPasswordNotification($token);
    $resetNotification->setName($this->name);

    $this->notify($resetNotification);
}
Tasiatasiana answered 20/11, 2016 at 12:38 Comment(8)
But that gives the error Undefined variable: username. How does the Notification Class get the User details?Pratique
@Pratique You have to add a class variable and set it. Updated the answer please checkTasiatasiana
Can you show me how do I initialize it in User model?Pratique
@Pratique User model is my guess, you may did differently. Do you know where App\Notifications\PasswordReset initialized or used in the app?Tasiatasiana
As per the docs (laravel.com/docs/5.3/passwords#password-customization) I created a custom Notification class PasswordReset and override the sendPasswordResetNotification method on the User model (code above). By default the $token is passed on to Notification class but not the User Data. In the notification class I was thinking of maybe find the user's name by checking the token in db table and then locate the user using the email address. But that seems like a long way and was wondering if there is an easier way to find the username for this use case. Hope it makes sense.Pratique
@Pratique Updated the answer again. Hope this will solve your issueTasiatasiana
@Pratique you can use $this->name in User model.. update the class name according to your codeTasiatasiana
Thank you so much. The update was exactly what I was stuck at. @Rimon Khan adding the same answer just now. Sending the user data from the override method in User Model works. It worked without setname and I am so happy it works now. I thank you so much for your kind help.Pratique

© 2022 - 2024 — McMap. All rights reserved.