Raj Makedreams
Raj Makedreams

Reputation: 11

Passing custom data to the email template of laravel notification class

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

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.

Upvotes: 1

Views: 1146

Answers (1)

Steven Lara
Steven Lara

Reputation: 1

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

Upvotes: 0

Related Questions