I am trying to send the SAME email to multiple addresses given from an array $emails.
I created a class called SendMail, and inside is a sendPost() method that accepts 2 arguments:
($post, $emails)
Here is my code:
class SendMail {
public static function sendPost($post, $emails)
{
Mail::send('acme.blog::mail.message', $post, function($message) {
$message->to($emails);
$message->from('mail#compuflexcorp.com', 'Compuflex Mail');
$message->subject($post['subject']);
$message->replyTo($post['email']);
});
}
}
The problem is, I keep receiving an error:
"Undefined variable $emails" on Line 14 of C:\...\SendMail.php
Line 14: $message->to($emails);
What I have tried:
I checked to see if I can access the $post and $emails variables inside of sendPost(), but outside of Mail::send(). And the answer is YES, I can access the information inside of $post and $emails inside of sendPost(), so the variables are, in fact, being passed to the sendPost() method.
I, at first, thought it had something to do with the fact that $emails is not one of the arguments for Mail::send(), so I put $post and $emails into one array called $vars, but then I got the error:
"Undefined variable $vars" on Line 14 of C:\...\SendMail.php
So, I realized that the issue seems to be that I can't pass any variables to Mail::send(), or in other words, I just don't know how to...
Any help would be greatly appreciated...
Thomas Yamakaitis
You need to pass the $emails variable as follows:
class SendMail {
public static function sendPost($post, $emails)
{
Mail::send('acme.blog::mail.message', $post, function($message) use ($emails) {
$message->to($emails);
$message->from('mail#compuflexcorp.com', 'Compuflex Mail');
$message->subject($post['subject']);
$message->replyTo($post['email']);
});
}
}
Related
When I was trying to override the default password reset function, I ran into some weird issue with closure.
$response = $this->broker()->reset(
// the 3rd variable $pwAge has to be passed via use()
$this->credentials($request), function ($user, $password) use($pwAge) {
$this->resetPassword($user, $password, $pwAge);
}
);
The 3rd variable $pwAge has to be passed to the closure via
use($pwAge)
if passed along side with the first two arguments as this:
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password, $pwAge) {
$this->resetPassword($user, $password, $pwAge);
}
);
I will get the following error when this function is called:
Symfony\Component\Debug\Exception\FatalThrowableError
Too few arguments to function App\Http\Controllers\Auth\ResetPasswordController::App\Http\Controllers\Auth\{closure}(), 2 passed in vendor\laravel\framework\src\Illuminate\Auth\Passwords\PasswordBroker.php on line 96 and exactly 3 expected
What am I missing here? Please advise, thanks.
The limit to the number of arguments in a closure is limited to amount of arguments provided to the function when it is called.
Whatever is calling that function (PasswordBroker.php in this case) provides a $user and $password; it has no knowledge of the $pwAge variable, and certainly does not know that it should pass it to the function.
You are able to use the variable by adding it to the scope of the closure using use ($pwAge).
Consider the following pseudo-code example:
function doSomething($cb) {
$result = doSomeStuff();
cb($result);
}
doSomething(function ($result) {
doSomethingElse($result);
});
For me, actually seeing that the closure was being called somewhere else helped me understand that I have no control over the parameters being passed to the closure. It's completely dependent on the code that calls it.
So if the closure needs extra "parameters", you just need to put them in scope:
doSomething(function ($result) use ($importantData) {
doSomethingElse($result, $importantData);
});
I am writing a simple router class which would allow you to execute a function when a route match is found. So, when you are defining routes, you would do something like this:
$message = 'Good morning!';
$router->addRoute('GET', 'welcome', function($message) {
echo $message;
});
Then, in the router class, this gets added to an array like:
public function addRoute($method, $pattern, $handler) {
$this->routes[$pattern] = ['method' => $method, 'handler' => $handler];
}
Once a match is found by comparing the pattern with the requested URL, I have:
return call_user_func($setting['handler']);
This gives me an error: Fatal error: Uncaught ArgumentCountError: Too few arguments to function
...so I tried using:
return call_user_func_array($setting['handler'], array($message));
...but this gives me: Notice: Undefined variable: message
How can I pass a function (including arguments, if existing) to execute within the router class using values stored on an array?
If you don't want to pass $message as an argument at call time, it should not be in the function parameter list. You're probably just looking to use the variable from the surrounding scope:
$message = 'Good morning!';
$router->addRoute('GET', 'welcome', function () use ($message) {
echo $message;
});
i use mailgun and the setting is done and i've test it and work, but i dont understand why i can't send email without array, here i tried using array but idk why it's error said Undefined variable: data
public function kirim(Request $request){
$data = array(
'email_address'=>$request->email_address,
'cc'=>$request->cc,
'subject'=>$request->subject,
'keterangantambahan'=>$request->keterangantambahan
);
Mail::send('laporan.kirim', $data, function($message) {
$message->from('christian7andrew#gmail.com', 'PuraBox');
$message->to($data['email_address']);
});
return redirect('/');
}
any idea how to use array corectly ??
Use a use.
Looks like you are using a php version which supports closures
Mail::send('laporan.kirim', $data, function($message) use ($data) {
$message->from('christian7andrew#gmail.com', 'PuraBox');
$message->to($data['email_address']);
});
The second parameter of the send() method is to set mail options. Does not place the variable inside the function body.
The use puts variables into the body of the function
I am well aware that globals are evil and this is an issue I will deal with later. It's not my codebase, but I've been assigned some cleaning up tasks.
Trying to smarten up a codebase, I decided to implement simple routing by using a package known as AltoRouter - I've worked with it before and it has worked fine for my purposes.
Now, the codebase is using a large amount of variables declared in the global scope. Usually, these variables are then fetched by using the globalkeyword. But for some reason, this doesn't work when I'm working inside a closure.
Consider this simple routing example:
<?php
require 'vendor/autoload.php';
$router = new AltoRouter();
$router->map('GET', '/shops/[i:id]', function($id) {
$_GET['shop_id'] = $id;
require 'go_to_shop.php';
});
$match = $router->match();
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
}
This calls my closure that sets a variable and requires a file.
This produces an error:
Fatal error: Call to a member function get() on null in
/vagrant/Core/CampaignHandler.php on line 71
Now, the code being called doing this is the following (line 70-71):
// Inside a method
global $serviceContainer;
$dispatcher = $serviceContainer->get("dispatcher");
The $serviceContainer is being declared by including a file early on:
$serviceContainer = new ServiceContainer();
$serviceContainer->set("dispatcher", new EventDispatcher());
Basically, if I move the contents of the closure outside of the closure, everything works perfectly - but as soon as I'm doing it from inside the closure, all variables accessed via the global scope is empty - and I have no idea as to why.
I've tried using use on the closure, this didn't work either.
I'm mostly looking for an explanation rather than a solution.
Globals are evil for a reason. You get the error because the global is not initialized at the time when function is being called. The mess of globals and requires is the exact issue and you are already trying to deal with it.
There is no problem to use globals in closure per se. This example works perfectly fine:
global.php:
<?php
class Foo {
public function bar() { return 'bar';}
}
$foo = new Foo;
test.php:
<?php
require 'global.php';
$test = function($param) {
global $foo;
echo $param, $foo->bar();
}
call_user_func_array($test, ['baz']);
so php test.php outputs bazbar;
I'm pretty sure that the $serviceContainer variable does not exist in the global scope, but the question leaves that part out.
Can't you pass the container to the anonymous function using a use( $serviceContainer ) statement? That'd be a far cleaner solution then having to rely on globals.
function($id) use( $serviceContainer ) {
$_GET['shop_id'] = $id;
require 'go_to_shop.php';
}
Off-topic: not sure what you're doing with that id variable later on and why you're putting it back into the $_GET variable like that, but please be careful.
Please check the manual for anonymus functions–also known as closures, which in real are objects.
http://php.net/manual/en/functions.anonymous.php
Theses callables have specific functions for extending their scopes.
See: Example #3 Inheriting variables from the parent scope.
$message = 'hello';
// No "use"
$example = function () {
var_dump($message);
};
$example();
// Inherit $message
$example = function () use ($message) {
var_dump($message);
};
$example();
Sure you want to assign a value to the $_GET global var?
$_GET['shop_id'] = $id;
The shop ID in your route you can extract from altorouter parameters. (See documentation.)
$router->map( 'GET', '/', function() { .. }, 'home' );
// assuming current request url = '/'
$match = $router->match();
/*
array(3) {
["target"] => object(Closure)#2 (0) { }
["params"] => array(0) { }
["name"] => 'home'
}
*/
Or if you want to store an ID for a session use $_COOKIES or $_SESSION global variables.
When I do a foreach() loop, the current array element's value $recipient is not defined on the line ->to($recipient). Why is this?
PHP Code (throws error)
foreach($recipients as $recipient) {
Mail::send('emails.invite', $data, function($m){
$m
->from('welcome#website.com', Auth::user()->name)
->to($recipient)
->subject('Auth::user()->name has invited you!');
});
}
Error
Notice: Undefined variable: recipient
PHP Code (NO error)
foreach($recipients as $recipient) {
echo $recipient;
}
You missed the use keyword. Change the code to :
foreach($recipients as $recipient) {
Mail::send('emails.shareListing', $data, function($m) use($recipient) {
$m
->from('share#asd.com', Auth::user()->name)
->to($recipient)
->subject('Auth::user()->name has shared a listing with you!');
});
}
See this documentation - especially the third example. Quote:
Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header.
It's because you're inside the scope of the function.
Assuming you're using the PEAR package here, I don't understand why you're passing a function at all: http://pear.php.net/manual/en/package.mail.mail.send.php
If you meant to be doing this, you can use the use keyword to pass the variable into the function scope:
function($m) use($recipient) {