Add a second action or a link to a Laravel Notification
Asked Answered
L

2

6

I am sending a notification using Laravel and am having trouble figuring out how to send a second action. Here is my code for the toMail method:

public function toMail($notifiable)
    {
    return (new MailMessage)
        ->subject($this->options['subject'])
        ->greeting($this->options['greeting'])
        ->line($this->options['contentParagraph1'])
        ->line($this->options['contentParagraph2'])
        ->action('Facebook', 'https://www.facebook.com/')
        ->line($this->options['contentParagraph5'])
        ->action('LinkedIn', 'https://www.linkedin.com/')
        ->line($this->options['contentParagraph3'])
        ->line($this->options['contentParagraph4'])
        ->salutation($this->options['salutation']);
}

What I am getting, is only the second action. It looks like the second action is overriding the first one. Is there a way to keep both actions or to use a link instead of a button?

Lundt answered 16/1, 2018 at 20:53 Comment(0)
S
8

The SimpleMessage class is designed for creating simple messages that have one call to action button, you can find the code that powers the functionality in Illuminate/Notifications/Messages/SimpleMessage.php and the template for the SimpleMessage emails can be found in Illuminate/Notifications/resources/views/email.blade.php — note the single button.

You can create more complex messages using the Markdown Mail Notifications feature, which will allow you to include as many buttons as you like. You can implement this like so:

  1. Run the command to generate a new notification and pass in the markdown option, e.g: php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
  2. Open the newly created template, e.g: views/mail/invoice/paid.blade.php
  3. Add as many buttons as you like, e.g:

    @component('mail::message')
      # Introduction
    
      @component('mail::button', ['url' => $url1])
      Button 1 Text
      @endcomponent
    
      @component('mail::button', ['url' => $url2])
      Button 2 Text
      @endcomponent
    
      @component('mail::button', ['url' => $url3])
      Button 3 Text
      @endcomponent
    
      Thanks,<br>
      {{ config('app.name') }}
    @endcomponent
    
  4. Replace your calls to SimpleMessage methods with a reference to your markdown template when constructing your email, e.g:

    return (new MailMessage)
      ->subject($this->options['subject'])
      ->markdown('mail.invoice.paid', $this->options);
    

The second parameter in the markdown method is an array to pass into your view, through this you can include the various values you'd like to include in your email, such as contentParagraph1, greeting and salutation.

Susceptible answered 16/1, 2018 at 21:44 Comment(0)
G
4

I implemented this workaround for adding a button to a standard SimpleMail object. Since MailMessage::line() can accept any object that implements Htmlable, you can put anything you want in it.

You still have to override the notification class to instead create an instance of MyMultiButtonVerifyEmail (instead of VerifyEmail), but that's easily done (and something you probably already had to do once updated email copy was provided).

Grrr, these default Laravel notification classes are not really reusable, are they?

use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Notifications\Action;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Lang;

class MyMultiButtonVerifyEmail extends VerifyEmail {

    public function toMail($notifiable) {
        $verificationUrl = ...;
        $resendUrl = ...;

        return (new MailMessage)
            ->line('some line')
            ->action(Lang::getFromJson('Verify Email Address'), $verificationUrl)
            ->line('another line')
            ->line($this->makeActionIntoLine(new Action(Lang::getFromJson('Request New Activation'), $resendUrl)))
            ->line(Lang::getFromJson('If you did not create an account, no further action is required.'));
    } // end toMail()

    private function makeActionIntoLine(Action $action): Htmlable {
        return new class($action) implements Htmlable {
            private $action;

            public function __construct(Action $action) {
                $this->action = $action;
            } // end __construct()

            public function toHtml() {
                return $this->strip($this->table());
            } // end toHtml()

            private function table() {
                return sprintf(
                    '<table class="action">
                        <tr>
                        <td align="center">%s</td>
                    </tr></table>
                ', $this->btn());
            } // end table()

            private function btn() {
                return sprintf(
                    '<a
                        href="%s"
                        class="button button-primary"
                        target="_blank"
                        style="font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, Helvetica, Arial, sans-serif, \'Apple Color Emoji\', \'Segoe UI Emoji\', \'Segoe UI Symbol\'; box-sizing: border-box; border-radius: 3px; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16); color: #fff; display: inline-block; text-decoration: none; -webkit-text-size-adjust: none; background-color: #3490dc; border-top: 10px solid #3490dc; border-right: 18px solid #3490dc; border-bottom: 10px solid #3490dc; border-left: 18px solid #3490dc;"
                    >%s</a>',
                    htmlspecialchars($this->action->url),
                    htmlspecialchars($this->action->text)
                );
            } // end btn()

            private function strip($text) {
                return str_replace("\n", ' ', $text);
            } // end strip()

        };
    } // end makeActionIntoLine()

}

For posterity, this was written for Laravel 5.8.32. There may be better ways of accomplishing this in later versions of the framework. YMMV.

Gout answered 6/2, 2020 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.