I have seen code like this:
function($cfg) use ($connections) {}
but php.net doesn't seem to mention that function. I'm guessing it's related to scope, but how?
use is not a function, it's part of the Closure syntax. It simply makes the specified variables of the outer scope available inside the closure.
$foo = 42;
$bar = function () {
// can't access $foo in here
echo $foo; // undefined variable
};
$baz = function () use ($foo) {
// $foo is made available in here by use()
echo $foo; // 42
}
For example:
$array = array('foo', 'bar', 'baz');
$prefix = uniqid();
$array = array_map(function ($elem) use ($prefix) {
return $prefix . $elem;
}, $array);
// $array = array('4b3403665fea6foo', '4b3403665fea6bar', '4b3403665fea6baz');
It is telling the anonymous function to make $connections (a parent variable) available in its scope.
Without it, $connections wouldn't be defined inside the function.
Documentation.
Related
I have got to the chapter of anonymous functions in php manuel. In the earlier chapter two methods of passing variables to a function are explained, namely, pass by value and pass by reference. Being a javascript developer, it was very unconfortable to see that functions do not have the access to the variables defined in the parent scope. Anyways, now they have come up with a third method to pass variables to a function -- by the use language construct. Please consider the following example:
$message = "hello";
$example = function () use ($message) {
var_dump($message);
};
$example(); //prints hello, as expected.
$message = 'world';
$example(); //prints hello -- not world.
The last call to $example should print "world", but it prints the older value of $message. Why is that? Instead if we had used either pass-by-value or pass-by-reference, the last function call would have printed world.
The use language construct captures/copies the passed variable at the time the anonymous function is defined. If you change that variable after the function definition, the function will not notice it:
$foo = 'baz';
$f1 = function() use ($foo) {
echo $foo;
};
$foo = 'boo';
$f1(); // baz
However, if the variable is an object, this rule doesn't apply, as PHP passes objects by reference*, always (* read Jeto's comment below for a more accurate description):
$foo = new StdClass();
$foo->bar = 'baz';
$f2 = function() use ($foo) {
echo $foo->bar;
};
$foo->bar = 'boo';
$f2(); // boo
I think the reason PHP has use is for partial function application:
function get_multiplier($factor) {
return function($num) use ($factor) {
return $num * $factor;
};
}
$multiply_by_4 = get_multiplier(4);
echo $multiply_by_4(5); // 20
i have this class (simple one just for example):
<?
class Test {
public function test1($a) {
$gen = function() {
$gen = function() {
global $a; // no effect
echo 'a='. $a; // how could i access $a from test1 parameter without passing?
};
$gen();
};
$gen();
}
};
$x = new Test();
$x->test1(123);
is there a way to access $a from test1 paramter inside last $gen function without passing it to the $gen() function?
Anonymous functions in PHP don't have an implicit variable scope like JavaScript does, so you need to specify which variables from the parent scope are needed. You do this with the use syntax:
$var = 123;
$fn = function() use ($var) {
// you can use $var here
}
$fn();
See also: Closures and scoping
You are missing the use statement. Refere to the 3rd example on PHP's documentation on closures.
This will work:
<?php
class Test {
public function test1($a) {
$gen = function() use ($a) {
$gen = function() use($a) {
echo 'a='. $a; // how could i access $a from test1 parameter without passing?
};
$gen();
};
$gen();
}
};
$x = new Test();
$x->test1(123);
I was wondering if it's possible to change and initialize variables in a function without passing arguments to the function. Here is what I want to achieve:
$foo = 'Lorem';
$array = array();
foobar($foo);
function foobar(){
if (strlen($foo)== 1)
$bar = 'Ipsum';
else
$array[] = 'error';
}
fubar();
function fubar(){
if (empty($fouten))
echo $bar;
}
$foo is a local (uninitialized) variable inside a function. It is different from the global variable $foo ($GLOBALS['foo']).
You have two ways:
$foo;
$bar;
$array = array();
function foobar(){
global $foo, $array, $bar;
if (strlen($foo)== 1)
$bar = 'Ipsum';
else
$array[] = 'error';
}
or by using the $GLOBAL array …
This is not really good practice though and will become a maintenance nightmare with all those side effects
Functions in php can be given arguments that have default values. The code you posted as written will give you notices for undefined variables. Instead, you could write:
function foobar($foo = null) {
if($foo) { // a value was passed in for $foo
}
else { // foo is null, no value provided
}
}
Using this function, neither of the below lines will produce a notice
foobar();
foobar('test');
In PHP, if you want to access variable in the outer scope, you need to declare it explicitly, e.g.
$foo = 'bar';
func (function() use ($foo) {
echo $foo;
});
But in JavaScript, they are implicit, e.g.
foo = 'bar';
func (function() {
console.log(foo);
});
What are the advantages and disadvantage of these two type of closure?
In PHP, if you want to access variable in the outer scope, you need to
declare it explicitly [...] use ($foo)
Technically, your function is not accessing $foo in the outer scope. To do that, you would need to:
$foo = 'bar';
$func = function() {
global $foo;
echo $foo;
};
This is not a closure. No variables are closed in with the function. If the value of $foo is changed, the next call to func will reflect that:
$func(); // bar
$foo = 'baz';
$func(); // baz
However, if we close in $foo with func:
$foo = 'bar';
$func = function() use ($foo) {
echo $foo;
};
$func(); // bar
$foo = 'baz';
$func(); // bar
func's $foo will retain it's value because it's been closed-over into the function.
To do the same in JavaScript, you simply create a function within a function and a closure will be created (giving the inner function access to the enclosing function's scope):
function getFunc(foo) {
return function () {
console.log(foo);
};
}
foo = "bar";
func = getFunc(foo);
func(); // bar
foo = "baz";
func(); // bar
What are the advantages and disadvantage of these two type of closure?
Using a "heap" type scope, as opposed to stack, so that the variable environment stays attached to the function allows first-class functions to be much more flexible as they can be passed around and recalled without worrying about creating (or passing in) a certain set of variables in order to make the function usable.
PHP does this because it doesn't know otherwise whether you meant to use the outer variable or not, since an unset variable acts like an empty string. This type of closure is therefore required for PHP, but not for Javascript.
I have an anonymous function which is supposed to call itself. However, I have no variable or function name at hand, so I was hoping to find a function that could do return "this" in context of functions. Is there such a thing?
Here's an example:
$f = function() use($bar, $foo) {
// call this function again.
};
Calling like this:
call_user_func(__FUNCTION__);
Leads to this:
Warning: call_user_func() expects parameter 1 to be a valid callback,
function '{closure}' not found or invalid function name
If I try to put $f in the use-list, then it says the variable is not defined (because it is not yet).
__FUNCTION__ cannot be used in anonymous functions
Pass the variable holding the anonymous function as a reference in the 'use' clause....
$f = function() use($bar, $foo, &$f) {
$f();
};
Tip of the hat to this answer.
Okay, I found out the way to do this:
$f = function() use(&$f) {
$f();
};
$f();
The key thing is to pass $f as a reference. Thus PHP does not try to pass a value but a reference to a memory slot.
I have an anonymous function which is supposed to call itself.
I prefer to use call_user_func_array(__FUNCTION__, $params); when calling a recursive function.
As your example doesn't have any arguments then i guess call_user_func(__FUNCTION__); would be better suited.
You would expect and hope the following code would work but that would be too easy.
$bar = 10;
$foo = 0;
$f = function() use (&$bar,$foo) {
if($bar){ // condition needed to prevent infinite loop
echo $bar-- . PHP_EOL;
call_user_func(__FUNCTION__); // wont work
}
};
$f();
The __FUNCTION__ "Magic constant" is unavailable to closures so the code needs to be adapted to allow the passing of the function variable. we can make the function available by passing it as a regular argument or via the use statement.
Function passed as argument
$bar = 10;
$foo = 0;
$f = function( $__FUNCTION__ = null ) use (&$bar, $foo) {
if($__FUNCTION__ && $bar){
echo $bar-- . PHP_EOL;
call_user_func( $__FUNCTION__, $__FUNCTION__);
}
};
$f ( $f );
Function passed via use statement
$bar = 10;
$foo = 0;
$__FUNCTION__ = function() use (&$bar, $foo, &$__FUNCTION__) {
if($bar){
echo $bar-- . PHP_EOL;
call_user_func( $__FUNCTION__ );
}
};
$__FUNCTION__();
Working example, click edit-> ideone it! to re-run code.
http://www.php.net/manual/en/language.constants.predefined.php
Edit: Posted before code was given. Of course it doesn't work on anonymous functions.
call_user_func(__FUNCTION__, $param1, $param2);
call_user_func_array(__FUNCTION__, $params);
function i_dont_know() {
call_user_func(__FUNCTION__,$params);
//or
$funcname = __FUNCTION__;
$funcname($params);
}