Passing custom data to the email template of laravel notification class

802 Views Asked by At

We are sending email notifications using laravel notifications and mailable class.

We have the following process : ** We are using laravel 7 **

  1. We dispatch the JOB dispatch(new JobEntitiesEmail($arr,$email));

  2. JobEntitiesEmail is a job we specifically wrote to send NOTIFICATIONS

`]

class JobEntitiesEmail implements ShouldQueue 
{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

/**
 * Create a new job instance.
 *
 * @return void
 */
public $tries = 3;
public $arr;
public $email;

public function __construct($arr,$email)
{
    $this->arr = $arr;
    $this->email = $email;
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{

    Notification::route('mail',$this->email)->notify((new EntitiesEmail($this->arr))->locale($this->arr['user_lang']));


}
} 
  1. We have app\Notifications\EntitiesEmail.php where we are creating a MailMessage object.

$mailmessage= (new MailMessage)->subject("subject of mail")

->line( __('messages.hello'))

->line(new HtmlString(__('messages.email_message')))

->action(__('titles.click'), url("google.com"));

  1. We have an email template in Resources\View\Vendors\mail
  • Both Email and Markdown ** We want to pass logo to the header file of mail which is located in resources\views\vendor\mail\html\header.blade.php**

like this :

$mailmessage= (new MailMessage)
      ->subject("email_template")
      ->line( __('messages.hello')..',')
      ->line(new HtmlString(__('messages.email_message')))
      ->action(__('titles.link'), url($link));
    }

Also want to access the passed variable $logoUrl in file resources\views\vendor\mail\html\message.blade.php

like

@component('mail::layout') 
    {{-- Header --}}
    @slot('header') 
            @component('mail::header', ['url' => config('app.url'), 'logoUrl' => $logoUrl ]) {{ config('app.name') }} 
        @endcomponent 
    @endslot

{{-- Body --}}

{{ $slot }}

{{-- Subcopy --}}
@isset($subcopy)
    @slot('subcopy')
        @component('mail::subcopy')
            {{ $subcopy }}
        @endcomponent
    @endslot
@endisset

{{-- Footer --}}
@slot('footer')
    @component('mail::footer')
        © {{ date('Y') }} <a href="https://google.com">{{ config('app.name') }}</a>. @lang(__('messages.copyright'))
    @endcomponent
@endslot
@endcomponent `

We have tried

  1. Using with method

$mailmessage= (new MailMessage)

->subject('New order')

->with(['logoUrl' => $logoUrl ])

It give data as a outrolines.

  1. Using Markdown

$mailmessage= (new MailMessage)

->subject('New order')

->markdown('Notification::email', ['logoUrl' => $logoUrl ]);

We get this data in viewData but not able to access this in template files.

1

There are 1 best solutions below

0
Steven Lara On

Well, I hope it is not too late, but I have had this issue two weeks ago, and it was difficult to find out how to fix it. At the end, doing some debug and use a lot dd() method. I could solve it like this

  1. Pass the $notifiable variable directly to the with() method
public function toMail(object $notifiable): MailMessage
    {
        $mail = (new MailMessage)
            ->subject('Hello World!')
            ->line('Go to our website')
            ->with($notifiable);
    }
  1. Then after you publish the default notification templates with
php artisan vendor:publish --tag=laravel-notifications
php artisan vendor:publish --tag=laravel-mail
  1. Then go to resources/views/vendor/mail/html/message.blade.php
  2. The slot variable will contain an Illuminate\Support\HtmlString this will contain the following info:
Illuminate\Support\HtmlString {#1856 // resources/views/vendor/mail/html/message.blade.php
  #html: """
    # Hello World!
    
    Go to our website
    
    {&quot;first_names&quot;:&quot;John&quot;,&quot;last_names&quot;:&quot;Doe&quot;,&quot;email&quot;:&quot;[email protected]&quot;,&quot;age&quot;:0}
    """
}

NOTE: The information at the end of the Illuminate\Support\HtmlString object is the $notifiable content we included and this variable is an instance of User.

User::make([
  'first_names' => 'John',
  'last_names' => 'Doe',
  'email' => '[email protected]'
]);
  1. To conclude you only need to use regular expressions and PHP built-in html_entity_decode and json_decode to get the data, like this:
<x-mail::layout>
    {{-- Header --}}
    <x-slot:header>
        <x-mail::header :url="config('app.url')">
        </x-mail::header>
    </x-slot:header>
 
    @php
        $htmlString = $slot->toHtml();
        $startIndex = strpos($htmlString, '{');
        $userJson = substr($htmlString, $startIndex);
        $htmlStringWithoutJson = str_replace($userJson, '', $htmlString);
        $bodySlot = new Illuminate\Support\HtmlString($htmlStringWithoutJson);
    @endphp

    {{-- Body --}}
    {{ $bodySlot }}

    {{-- Footer --}}
    <x-slot:footer>
        <x-mail::footer>
            @php
                $htmlString = $slot->toHtml();
                $startIndex = strpos($htmlString, '{');
                $userJson = substr($htmlString, $startIndex);
                $userJson = html_entity_decode($userJson);
                $user = json_decode($userJson);
            @endphp

            <p>
                <div class="footer-primary">
                    This email was sent to <span class="email">{{$user->email ?? '[email protected]' }}</span>. 
                </div>
            </p>

{{-- YOUR CODE ... --}}

NOTE: If you pay close attention, I used two PHP code block in the view

  1. In the first one I just removed all data that comes from $notifiable variable, since this is an Illuminate\Support\HtmlString it will be shown on the email structure, which is what we do not want.
  2. And in the second one I just extract the data by removing html entities and decode it to a JSON format so I can easy access to it.

I hope it helps, thanks for reading!

IF THERE IS A BETTER WAY TO DO IT, PLEASE LET ME KNOW, I WILL BE HAPPY TO READ IT