0

I am trying to pass non-model data to my email blade. I however keep getting this error.

Cannot unpack array with string keys

I have tried using the following post but didn't get to resolve the issue I am having.

Here is my controller:

$data = ['email'=> $email, 'token'=> $token, 'name'=> $name];
        sendMailWithMailerClass($email, '\App\Mail\ApplicantSetPasswordMail', $data);
        
...



function sendMailWithMailerClass($mailTo, $mailerClass, $mailerClassParams)
{
  
    try{
        Mail::to($mailTo)->send(new $mailerClass(...$mailerClassParams));
    } catch (Exception $e) {
       
    }
}
The email class is here below

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

class ApplicantSetPasswordMail extends Mailable
{
    use Queueable, SerializesModels;
    public $data;

    
    public function __construct($data)
    {
        $this->data = $data;
    }

    
    public function build()
    {
        return $this->markdown('emails.applicant_set_password', compact('data'));
    }
}

Here is my email view:

<!DOCTYPE html>
<html lang="en" >
<head>
</head>

<body >
<center>
    
    <p>Dear {{ $data['name'] }},</p>
    <p style="margin-bottom: 25px;">Text</p>
    <a href="{{ URL::to('/').'/url/?email='.$data['email'].'&token='.$data['token'] }}" >Set Password</a>
                     
</center>
</body>
</html>
mykoman
  • 1,715
  • 1
  • 19
  • 33

2 Answers2

2

The splat operator ... that you try to use on the line new $mailerClass(...$mailerClassParams) cannot work with an associative array like your $data

I can see that the constructor you use for your mailable class is public function __construct($data) so you should be able to just use new $mailerClass($mailerClassParams)

If you do have a mailable class with multiple parameters in the constructor such as public function __construct($email, $token, $name) then you can either still pass it as 1 array parameter and check the content of the array passed. or use new $mailerClass(...array_values($mailerClassParams)). However, take note that if you use end up using array_values() then the order of the array actually matters as that is how it will map the parameters so that first entry of $mailerClassParams array will always be the first parameter, as such this is not the recommended way.

function sendMailWithMailerClass($mailTo, $mailerClass, $mailerClassParams)
{
    try{
        // Remove ... splat operator here
        Mail::to($mailTo)->send(new $mailerClass($mailerClassParams));
    } catch (Exception $e) {
       
    }
}

// make sure all your $mailClass constructors take 1 parameter
public function __construct($data)
{
    $this->data = $data;
}

OR

function sendMailWithMailerClass($mailTo, $mailerClass, $mailerClassParams)
{
    try{
        // Remove keys of the associative array with array_values
        Mail::to($mailTo)->send(new $mailerClass(...array_values($mailerClassParams)));
    } catch (Exception $e) {
       
    }
}

// make sure all constructor takes correct parameters in the correct order
public function __construct($email, $token, $name)
{
    $this->data = [
        'email' => $email,
        'token' => $token,
        'name' => $name,
    ];
}
Helioarch
  • 1,158
  • 5
  • 18
  • The first error has been resolved. How am I supposed to access the variables in my blade please. I used {{ $name }} and {{ $data['name'] }} both threw errors. I used the first approach – mykoman Jun 23 '20 at 05:53
  • @mykoman instead of `compact($data)` pass `$this->data` as the `data` property is already an array, then you should be able to use it in your view with {{ $name }} – Helioarch Jun 23 '20 at 06:00
1

It is implemented since PHP 8.1.

$args = [
    ...['z' => 2, 'x' => 3],
    ...['y' => 1, 'x' => 4],
];

class Foo
{
    public function __construct(int $x, int $y, int $z)
    {
        echo <<<OUTPUT
            x = $x
            y = $y
            z = $z
        OUTPUT;
    }
}

new Foo(...$args);
/* Output:
 * x = 4
 * y = 1
 * z = 2
 */

Test it online!

MAChitgarha
  • 3,728
  • 2
  • 33
  • 40