Passed data to custom email view is not avaliable - php

As you know, send a email via laravel is so simple as:
// setting data
$data = array(
'band' => 'Kings of leon'
);
// send email
\Mail::send('emails.activation', $data , function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
Then in /app/views/emails/activation.blade.php view could contains a not complicated structure:
My fav band is {{ $band }}. Here a logo:
<img src="{{ $message->embed('/img/logo_small.png') }}" alt="">
Views path:
/app/config/views.php
'paths' => array(DIR.'/../views', ),
Everything above works like a champ. However, if you change the email view from emails.activation to another one belonging in different path from default cause two problem:
The $message var is not longer available in the view
The $data arg is not passed to the view.
So, lets see:
// setting data
$data = array(
'band' => 'Kings of leon'
);
// send email using different view outside of default path
\Mail::send('theme::views.emails.activation', $data , function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
The view is successfully found, but when it is compiled throws two exception stating undefined var: $message and undefined var: $band.
am I missing an extra-configuration? or is it a bug? Thank you.
update
After an exhaustive revision, the problem resided in a calling of the email view twice in the same controller, for example:
$stringLocation = \Theme::getViewLocation('emails.activation');
... more stuff here
\Mail::send($stringLocation, $data , function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
So, calling getViewLocation() compiled the view, and of course, the data were not present at this exact point. My bad was believe that the error was in \Mail::send line than getViewLocation.

Related

Use blade in blade

In my database I save texts that contains blade markup like:
Hello {!! $name !!} how are you today.
I pass this text to my email template in a variable $text. In the email I use {!! $text !!} to get the text in the mail. However when the email is send it shows the {!! signs instead of the variable (which is also passed).
How can I save blade markup in my database and pass it to my code where it needs to replace {!! something !!} with the right variable?
My mail function.
$email = $order->email;
$name = $order->billingname;
//The text From the database.
$emailText = Email::findOrFail(5);
$mailtext = $emailText->text;
Mail::send('emails.tracktrace', ['text'=>$mailtext'email' => $email, 'name' => $name],
function ($m) use ($code, $email, $name) {
$m->from('info#domain.com', 'domain');
$m->to($email, $name)->subject('Track your package!');
});
Update
I've got a workaround where i do:
$mailtext = str_replace('[name]', $name, $mailtext);
this way the user can use [name], I would still like to know how to use it with blade only.
You can't have a blade-string to compiled PHP code without rendering it at the first place. You should try your custom rendering class or invoke Blade.
public function send()
{
$emailText = Email::findOrFail(5);
$name = $order->billingname;
$mailtext = \Blade::compileString($emailText->text);
ob_start();
eval("?> $mailtext <?php");
$mailtext = ob_get_clean();
Mail::send('emails.tracktrace', [
'text' => $mailtext,
'email' => $email,
'name' => $name
],
function ($m) use ($code, $email, $name) {
$m->from('info#domain.com', 'domain');
$m->to($email, $name)->subject('Track your package!');
});
}
However it's not safe as there is an eval. [Tested in Laravel 5.1]
Also there are some well written packages out there for this specific purpose, like StringBladeCompiler v3
I have used the email like below, all the dynamic variables to be replaced are like '{{ $name }}' in the email template.
I created a data array and used it directly with the mail library. This way you can replace multiple dynamic variables in mail template on the go.
You need to keep your text in the email template and use dynamic vales from database.
If your text for the email is dynamic and comes from database, you can use the text in place of the email template in the function and pass $data variables array to replace them all in one go.
$data = array('name' => $customer->Name, 'InvoiceID' => $dueinvoice["InvoiceNumber"],'AmountDue' => $dueinvoice["AmountDue"],'DueDate' => $duedate ,'CurrencyCode' => $dueinvoice["CurrencyCode"]);
\Mail::queue('emails.DueDateNotification',$data, function($message) use($customer)
{
$message->subject('DueDate Notification');
$message->to($customer->EmailAddress);
});
Another thing is try to use the 'queue' function for mail as its reduces load and add the email to laravel email queue and sent one by one
Hope this helps you :)

Passing form input data to the mail view - Laravel

I am making a form which will send an email.
Currently its a generic blade form which points to /admin/newemail
I have my route and for testing the mail is sent from that route:
Route::get('admin/newemail', function()
{
$email = 'email#hotmail.com';
$data = Input::all();
Mail::send('emails.newemail', $data, function($message) use ($email){
// $message details
});
});
And then to trial this I tried in my view: (there is a field name of 'subject' in my form)
echo Input::get("subject");
I actually have two issues. (I am using the log driver)
1) The email is not showing in the log, its just showing [] []
2) The data is not showing neither and its blank.
If I simply have:
echo "hello!";
Then the log will output hello, likewise If i change my mail data variable to an array:
$data = array('test' => 'test');
Then in the view:
echo $test;
That also works. But I want it to take my inputs from my form.
Here, Try this:
Mail::send('emails.welcome', array('key' => 'value'), function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
Here, key will be any name which you want to give and value will be the data you want to assign, it could be form data or could be from database.
Now, after doing that create a file in your views/emails as welcome.blade.php and to fetch the value passed through mail function use:
{{ $key }}
Above is the blade format to represent data.
For more info on mail, visit this, and for blade templates go here.
See, if that helps you.
Mail::send('emails.welcome', Input::all(), function($message)
{
$message->to('foo#example.com', 'John Smith')->subject('Welcome!');
});
and in your view you have
{{Input::get("subject")}}
This is what i use myself and it works perfectly.

Laravel 4 Queued Mailing throws error while directly sending works

I have a Laravel 4 app where I need to send certain emails to users. I have no idea why but I keep getting this error on my test server (it does not happen on my local vagrant box)
Argument 1 passed to Illuminate\Mail\Mailer::getQueuedCallable() must
be of the type array, null given, called in
blablabla/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php
on line 238 and defined
I tried resetting everything: database, clean clone from git. None of these worked. I also cleared my browser cache and cookies out of desperation. I am using Sync queue. So it's not even an actual queue.
Mail::send works just fine. Mail::queue throws the error above.
I literally started to pull my hair out so any help will be greatly appreciated.
Here is my code:
This is my BookingMailer class that extends Mailer class.
// partner bir arabanın rezervasyonuna onay verdiğinde müşteriye gönderilecek ödeme linki
public function sendPaymentLinkToCustomer($customer, $partner, $booking) {
$view = 'emails.bookings.request_confirmed';
$data = [
'user' => $customer->full_name // string,
'partner' => $partner->display_name // string,
'reference' => $booking->reference // integer,
'booking_id' => $booking->id // integer
];
return $this->sendTo($customer, 'Booking Request Confirmed', $view, $data, true, true);
}
And this is my Mailer class that actually queues the mail.
public function sendTo($user, $subject, $view, $data = array(), $admin_copy=false, $send_as_pm=false)
{
Mail::queue($view, $data, function ($message) use ($user, $view, $data, $subject, $admin_copy) {
$message = $message->to($user->email)->replyTo(Config::get('mail.from.address'), Config::get('mail.from.name'))->subject($subject);
return $message;
});
}
Here is the solution to this problem (at least in my case)
I was including the user first and last name to the mail. I was only showing the first letter of the last name, though. And I was using substr for a UTF-8 string, and that's why sometimes it returned problematic characters that get inside the data array and ultimately cause the queue to break.
When i used mb_substr instead of substr, my problem disappeared.
Phew, I thought I would never figure this one out on my own.

how to make adminEmail dynamically in yii framework

currently the adminEmail is set in the params.php file. I am trying to change the 'adminEmail' dynamically and then I can assign the email value I want. There is the code in the params.php.
return array(
// this is displayed in the header section
'title' => 'title here',
// this is admin email
'adminEmail' => 'admin#email.com',
But the admin emails can be more than one(eg. admin1#email.com, admin2#email.com), how can I set admin email dynamically in params.php ?
Thanks in advance!
You can try set multiple emails on adminEmail, and at runtime access it using index. E.G
//asign multiple email ids to adminEmail as array
'params'=>array(
// this is used in contact page
'adminEmail'=>array('webmaster#example.com','sany#gmail.com','xxx#yahoo.com','webmaster2#example.com')
),
//access it using array index at runtime as your requirement
<?php echo Yii::app()->params['adminEmail'][1];?> //sany#gmail.com
<?php echo Yii::app()->params['adminEmail'][2];?> // xxx#yahoo.com
OR
Create a static method on a class that will generate dynamic email ids and
then set it to your adminEmail param .e.g
class Email
{
public static function generateEmailIds()
{
//or any other way to generate email ids or id
return array('webmaster#example.com',
'sany#gmail.com',
'xxx#yahoo.com');
}
}
'params'=>array(
// this is used in contact page
'adminEmail'=>Email::generateEmailIds(),
)
Well, although I don't recommend this approach, what you want to do can be done like this:
You need to store your array in a file in serialized form (that is, call function serialize() on it. That will turn the array into a string.
You can read the file and unserialize it (that is, call function unserialize() on it. That will turn the string that you read form file back into a PHP array.)
$handle = fopen('path/to/file','rb');
$contents = fread($handle,999).
$array = unserialize($contents);
set 'adminEmail' to what you want it to be:
$array['adminEmail'] = 'new#email.com;
or even
$array['adminEmail']= array(..lots of emails..);
then you need to turn the array into a string and write the array back to file. Like this, for example:
$serialized_contents = serialize($array);
fwrite($handle, $serialized_contents);
There may be more efficient ways to do this if you want to.

CodeIgniter - Variable scope

I have a controller which I use for a login form. In the view, I have a {error} variable which I want to fill in by using the parser lib, when there is an error. I have a function index() in my controller, controlled by array $init which sets some base variables and the error message to '':
function index()
{
$init = array(
'base_url' => base_url(),
'title' => 'Login',
'error' => ''
);
$this->parser->parse('include/header', $init);
$this->parser->parse('login/index', $init);
$this->parser->parse('include/footer', $init);
}
At the end of my login script, I have the following:
if { // query successful }
else
{
$init['error'] = "fail";
$this->parser->parse('login/index', $init);
}
Now, of course this doesn't work. First of all, it only loads the index view, without header and footer, and it fails at setting the original $init['error'] to (in this case) "fail". I was trying to just call $this->index() with perhaps the array as argument, but I can't seem to figure out how I can pass a new $init['error'] which overrides the original one. Actually, while typing this, it seems to impossible to do what I want to do, as the original value will always override anything new.. since I declare it as nothing ('').
So, is there a way to get my error message in there, or not? And if so, how. If not, how would I go about getting my error message in the right spot? (my view: {error}. I've tried stuff with 'global' to bypass the variable scope but alas, this failed. Thanks a lot in advance.
$init musst be modified before generating your view.
To load your header and footer you can include the following command and the footer's equivalent into your view.
<?php $this->load->view('_header'); ?>
to display errors, you can as well use validation_errors()
if you are using the codeigniter form validation.
if you are using the datamapper orm for codeigniter you can write model validations, and if a query fails due to validation rule violation, you get a proper error message in the ->error property of your model.
Code for your model:
var $validation = array(
'user_name' => array(
'rules' => array('required', 'max_length' => 120),
'label' => 'Name'
)
);
You might try this:
function index() {
$init = array(
'base_url' => base_url(),
'title' => 'Login',
'error' => ''
);
$string = $this->parser->parse('include/header', $init, TRUE);
$string .= $this->parser->parse('login/index', $init, TRUE);
$string .= $this->parser->parse('include/footer', $init, TRUE);
$this->parser->parse_string(string);
}
In parse()you can pass TRUE (boolean) to the third parameter, when you want data returned instead of being sent (immediately) to the output class. By the other hand, the method parse_string works exactly like `parse(), only accepts a string as the first parameter in place of a view file, thus it works in conjunction.

Categories