Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincej's avatar
Level 15

Mailable: Non Numeric Value Encountered

I need to pass an alpha-numeric variable $ref into the email I need to send to the customer. This references their quotation data. Example: jac123456-10.

However when it hits the Mail class I get the error. See Here:

class SendCustomerQuote extends Mailable
{
    use Queueable, SerializesModels;

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


    public function build()
    {
        return $this->markdown('emails.customer.customer_quote'/$this->ref);  // HERE IS THE ERROR. 
    }
}

I have read on SO that this is a "feature" of PHP 7.1 & 7.2

So - How do I get around this problem, with out changing all my references to a pure numeric??

Many thanks !

0 likes
30 replies
Snapey's avatar

why do you have a divide symbol there?

Cronix's avatar
Cronix
Best Answer
Level 67

You don't need to pass variables to the view. You make them public properties of your mailable class. All public properties are passed to the view automatically.

class SendCustomerQuote extends Mailable
{
    use Queueable, SerializesModels;

    public $ref; // create public property as $ref

    public function __construct($ref)
    {
        $this->ref = $ref; // assign value to $this->ref
    }

    public function build()
    {
        return $this->markdown('emails.customer.customer_quote'); 
    }
}

then in the emails.customer.customer_quote view, you just access $ref like you normally would, {{ $ref }} etc.

https://laravel.com/docs/5.5/mail#view-data

vincej's avatar
Level 15

@snapey Thanks for your reply.. The forward slash was my attempt at creating a url.

@Cronix Thanks for that. Your instructions allowed me to eliminate the non numeric problem. However, I have a new problem as follows:

  Mail::to($customer['email1'])->send(new SendCustomerQuote());

In this line I need to send within the email a very specific customer reference number such that when they click on the email, the controller accesses specifically their Quote.

Therefore I need to pass into the SendCustomerQuote class a specific reference.

I have tried gazzilions of different statements for the ->send(new SendCustomerQuote()) and none of them work. So, for example:

SendCustomerQuote($ref);

SendCustomerQuote($this->ref);

SendCustomerQuote(save_quote($this->ref));

And they all fall.

I have looked at the laravel docs ( thank you !) and the order they use assumes there is only 1 order in their table. In my quotations table I have dozens of quotations which are all accessed via a reference number.

How do I specifically get the reference number into the final email so that when the use clicks on a button it will go to the set controller with the reference number ?

Many thanks !!

Snapey's avatar

Hi Vince

Where you send the email it is as you have now, but you have to pass the data you want the mail to use into the constructor

  Mail::to($customer['email1'])->send(new SendCustomerQuote($ref));

I don't understand the context of the $ref in this case but you may be better passing the whole quote into there so that you can access any information about the quote, or related models. Eg, the quote might have a title, or you might want the customer's full name.

So perhaps

  Mail::to($customer['email1'])->send(new SendCustomerQuote($quote));

Now you are passing the quote into the mailable. In there you need to persist it to a public property

    public $quote;

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

    public function build()
    {
        return $this->markdown('emails.customer.customer_quote'); 
    }

Now in the mail template you can use $quote and any of its attributes or relationships

eg

Your reference number is {{ $quote->ref }}

Hope thats a little clearer

vincej's avatar
Level 15

HI Snapey, Thanks for all your help. I'm still screwing up, however, I believe I know where I am screwing up! :o)

This is where I am going wrong:

Mail::to($customer['email1'])->send(new SendCustomerQuote($newQuotation));

Essentially $newQuotation is not correct and is giving me this error:

Argument 1 passed to App\Mail\SendCustomerQuote::__construct() must be an instance of App\QuotationController, instance of App\Models\Quotation given, called in /var/www/auburntree/app/Http/Controllers/QuotationController.php on line 188

Ok - I think I understand what the error is telling me, "must be an instance of App\QuotationController". But here is my issue. I don't know how to do this. I've tried everything I can think of. My controller has a gazzilion functions in it. I have tried referencing my constructor values, but that is why it is giving the error.

How do I isolate specifically what it wants?

Many thanks, Vince

jimmck's avatar

@vincej Emails have no idea of your servers PHP class structure. What does your URL specifically look like as formatted in the email? Does the URL contain enough unique information to identify the order?

Snapey's avatar

Presumably in the constructor of the mailable you have declared the type of object it should receive ?

jimmck's avatar

@Snapey @vincej Then you could route those URL's to a different class of constructor. You can construct the email to use a whole different set of Controllers than what a normal webpage might call. Share the backend processing once it has been properly routed.

Snapey's avatar

routing has got nothing to do with it

vincej's avatar
Level 15

Frankly guys, I have no idea what I am doing here. My mailable constructor looks like this:

protected $quotation

  public function __construct(QuotationController $quotation)
    {
        $this->quote = $quotation;
    }

I have tried changing the mail::to to this, ie an instance of my function in my controller and I still get an error, although a different error:

 Mail::to($customer['email1'])->send(new SendCustomerQuote($this->save_quote($ref)));

Resulting Error:

"Argument 1 passed to App\Http\Controllers\QuotationController::save_quote() must be an instance of Illuminate\Http\Request, string given, called in /var/www/auburntree/app/Http/Controllers/QuotationController.php on line 188 ◀"

Using this, it wants to see an instance of Request, however, $ref is not part of Request, it is generated through code.

Sorry to be a pain. Many Thanks !!

Snapey's avatar

you need to pass in the model or just your reference. Not the controller !

show where you call the mailable in context. I assume this is within a controller?

vincej's avatar
Level 15

Sure, I passed in the model first time around, and it complained that I had passed in the model and it wanted an instance of the controller. Ok, so I give it an instance of the controller and it complains again, saying I passed in a string . Clearly I am doing something very stupid here. Ok here is an abbreviated Controller:

class QuotationController extends Controller
{

    protected $quotation;
    protected $workorder;
    protected $categories;
    protected $project_summary;
    protected $project_templateDetails;
    protected $save_quote;


    
    public function __construct(Quotation $quotation, Workorder $workorder, Nested_Categories $categories, Project_template $project_templateDetails, Project_summary $project_summary){

        $this->quotation = $quotation;
        $this->workorder = $workorder;
        $this->categories = $categories;
        $this->project_templateDetails = $project_templateDetails;
        $this->project_summary = $project_summary;
        $this->middleware('auth:admin', ['except' => ['customer_quote']]);
    }


//  HERE ARE LOADS OF FUNCTIONS


 public function save_quote(Request $request)

// HERE IS LOADS OF CODE. 

        {
        if( $email == 'email'){
                Mail::to($customer['email1'])->send(new SendCustomerQuote($this-                            >save_quote($ref)));
            }

    }

}

Snapey's avatar

here in your mailable

public function __construct(QuotationController $quotation)
    {
        $this->quote = $quotation;
    }

you are saying that the mailable MUST be passed an instance of QuotationController

YOU decide what you want as the parameters for the mailable. If you only want a string then remove the reference to QuotationController and just pass $ref

Its up to you.

jimmck's avatar

Yeah no need for routes. URL cannot pass class instances! Controllers cannot receive class instances directly from a URL. Use Middleware to inspect a URL from a ROUTE and maybe construct a class instance and PASS it to the controller. Hence the word Middleware. Or if you are more adventurous your code Infer the Class and constructor data in the URL but really why?

Emails have separate URL links than webpages. Different mediums. Emails contains contain more static and/or time dependent data.

Snapey's avatar

@jimmck stop keep going on about urls - you are just confusing things. We have not got to handling links in emails yet. This question is JUST about successfully calling the mailable and sending the email.

vincej's avatar
Level 15

@Snapey thanks again for all your help. It is much appreciated.

I'm not getting very far very fast with this. I have adapted my mailable as per your advise.

I have tried umpteen different entries into the following SendCustomerQuote() , they all fail for what ever reason.

   Mail::to($customer['email1'])->send(new SendCustomerQuote());

ERROR

"Too few arguments to function App\Mail\SendCustomerQuote::__construct(), 0 passed in /var/www/auburntree/app/Http/Controllers/QuotationController.php on line 18 ▶"

If I enter $ref it fails because it is a string.

If I enter Quotation it fails because it is a model

It keeps telling me I need an instance of QuotationController. Ok, when I enter that, it fails because there are too few arguments. Ok, when I enter QuotationController::save_quote($ref) I get an infinite loop.

I can only assume that I have not formulated my constructor properly.

I am at a total loss as to what to do - any ideas how to complete new SendCustomerQuote() ?

Many thanks!

Cronix's avatar

Like you were before, Mail::to($customer['email1'])->send(new SendCustomerQuote($newQuotation)); You have to send the quotation to the mailable.

For now, try changing your constructor to

public function __construct($quotation) // remove QuotationController 
{
    $this->quote = $quotation;
}
vincej's avatar
Level 15

@Cronix Do you mean change my constructor in my QuotationController or in the mailable?

Cronix's avatar

whichever one had the above line in it. I'm getting lost in the things that have been altered so far...

vincej's avatar
Level 15

Ok, I changed it in the mailable. However I am still getting the error

Too few arguments to function App\Mail\SendCustomerQuote::__construct(), 0 passed in /var/www/auburntree/app/Http/Controllers/QuotationController.php on line 18 ▶"

My send mail looks like this:

Mail::to($customer['email1'])->send(new SendCustomerQuote());

Cronix's avatar

Yes, as I said you need to send the quote to the SendCustomerQuote() class, like I showed.

Also, go back and read snapeys posts on the previous page. He had the right answer, and you're making it more complicated now and we're going in circles. You had it working. The only thing you didn't do is change what he said (and I said above) about the constructor.

You were getting this error in the SendCustomerQuote constructor

Argument 1 passed to App\Mail\SendCustomerQuote::__construct() must be an instance of App\QuotationController, instance of App\Models\Quotation given, called in /var/www/auburntree/app/Http/Controllers/QuotationController.php on line 188

He, and I, said to fix it like

public function __construct($quotation) // remove QuotationController 
{
    $this->quote = $quotation;
}
vincej's avatar
Level 15

I don't know how to send the quote. That is my big problem. What ever I add to Mail::to($customer['email1'])->send(new SendCustomerQuote(DON'T KNOW WHAT TO PUT IN HERE)); it fails as described a few posts above.

Snapey's avatar

Because your mailable is told to expect something and you are not giving it.

Remove mailable's expectation.

Change the constructor of the mailable


public function __construct($quotation) // remove QuotationController 
{
    $this->quote = $quotation;
}

Call the mailable like this;

   Mail::to($customer['email1'])->send(new SendCustomerQuote('a temporary string'));

You are just passing a variable into a class. Its basics! Stop thinking about it as a mailable and just think 'right, i just need to pass x to this function'

Cronix's avatar

Mail::to($customer['email1'])->send(new SendCustomerQuote(DON'T KNOW WHAT TO PUT IN HERE));

you put the reference id there, since that's the thing you're trying to send as a variable in the email view, right?

show your

public function save_quote(Request $request)

method, not just the line where you're sending the email. I'm sure that's where this mysterious $ref_id is coming from that needs to be passed to the mailable.

vincej's avatar
Level 15

Ok, the $ref is not part of $request. Perhaps this is my problem. It is dynamically generated like this:

$r= substr($customer['lastname1'],0,3);
        $carbon = Carbon::today();
        $format = $carbon->format('dmy');
        $rand = mt_rand(0,99);

        $ref = $r.$format.'-'.$rand;

Ok, so, when I do Mail::to($customer['email1'])->send(new SendCustomerQuote($ref));

I do not get an error, however, I am not getting the ref passed through into the email either

Here is my mailable:

class SendCustomerQuote extends Mailable
{
    use Queueable, SerializesModels;

    public $quotation;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($quotation)
    {
        $this->quote = $quotation;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.customer.customer_quote');
    }
}


Cronix's avatar

I do not get an error, however, I am not getting the ref passed through into the email either

public $quotation;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($quotation)
    {
        $this->quote = $quotation;
    }

because you create a public $quotation variable, but in the constructor you set $this->quote... so it didn't get assigned.

change public $quotation to public $quote, and in the view, reference {{ $quote }} for the output.

vincej's avatar
Level 15

Brilliant ! I am getting the $quote value in my email ! However, next challenge is getting it to form part of the url so that when the button is clicked it goes to the correct quote.

('mail::button', ['url' => 'http://192.168.1.92/view_customer_quote'])

When I place $quote outside this statement, it doe not form part of the url. When it is placed inside the statement it gives an error.

Cronix's avatar

so ['url' => 'http://192.168.1.92/view_customer_quote/' . $quote]) doesn't work?

btw, you should use the url() helper and not hardcode your url. That will make upgrading a pain in the ass since you'll have to manually update every place you hardcoded the urls...

url('view_customer_quote/' . $quote) https://laravel.com/docs/5.6/helpers#method-url

it will use whatever host url you have set for APP_URL in your .env file, so all you have to do is change that one variable when you change hosts (or put this on a live server).

vincej's avatar
Level 15

Hallelujah !!! Success !! The url us hardcoded only because I have been following a tutorial on YouTube's DevMarketer. Thanks for the tip, I will input that.

@Snapey A very Big thanks for your help as well.

Without you guys, so many of us would have givenup. You guys are rock stars.

Please or to participate in this conversation.