PHP equivalent to [&, epsilon] C++ "Capturing" variables in lambda? - php

Is there a way I can pass any variable currently in scope by reference to a lambda function without listing them all in the use(...) statement?
Something like
$foo = 12;
$bar = 'hello';
$run = function() use (&) {
$foo = 13;
$bar = 'bye';
}
// execute $run function
Resulting in $foo equal to 13 and $bar equal to 'bye'.

TL;DR The short answer is no. You need to name the variables
You don't need closure variables for this. It's not even valid to use use with named functions since it won't have a nested lexical scope. Use the global keyword to make the variables "dynamic". You have to name all the variables that are special.
$foo = 12;
$bar = 'hello';
function run() {
global $foo,$bar;
$foo = 13;
$bar = 'bye';
}
run();
print "$foo, $bar\n"; // prints "13, bye"
For a lexical anonymous functions you need to name all variables with the use keyword and use & to get it referenced:
$foo = 12;
$bar = 'hello';
$run = function () use (&$foo,&$bar) {
$foo = 13;
$bar = 'bye';
};
call_user_func($run);
print "$foo, $bar\n"; // prints "13, bye"

You could use get_defined_vars() along with extract():
$foo = 12;
$bar = 'hello';
$vars = get_defined_vars();
foreach (array_keys($vars) as $var) {
$vars[$var] = &$$var; // keep refs of all variables from current scope
}
$run = function() use($vars) {
extract($vars, EXTR_REFS);
$foo = 13;
$bar = 'bye';
};
// execute $run function
$run();
print $foo; // prints 13
print $bar; // prints bye

Related

Reference assignment to a more complex variable

Let's say I have an example like this one:
$foo = 'Hello ';
$bar = 1;
$abc =& $foo . $bar;
if (true) {
++$bar;
if (true)
{
++$bar;
}
}
echo $abc;
I am expecting $abc to return Hello 3, but it actually returns Hello only. I'm really confused. Is there something I've gotten wrong with references in PHP?
A reference variable is like an alias to the same object/variable, and it can only reference one variable at a time.
I'm not really sure how to help your situation because I don't know what you're trying to do, but..
$foo = 'Hello ';
$bar = 1;
$abc =& $bar;
++$bar;
++$bar;
echo $foo . $abc;
http://www.php.net/manual/en/language.references.whatdo.php

change and initialise variables in a function

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');

PHP use() function for scope?

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.

How to replace a function with unknown argument names?

This is what I want to do:
$var = "foo";
$unknown = "";
function do($arg1, $arg2) {
$arg2 = "bar";
magic($arg2);
}
do($var, $unknown);
echo $unknown;
This should return: bar
I know that this would work if I'd define my function like this:
function do($arg1, $unknown) {
global $unknown;
$unknown = "bar";
}
As you probably guessed already, the variable name of $unknown is unknown.
I need this because I'm writing a PHP sandbox using apd. I want to replace exec($cmd, $ret) in a PHP script I don't known with my own function.
So if the unknown PHP script looks like this:
$foo = "";
exec('whois google.com', $foo);
echo $foo;
I'll have a problem replacing exec with my own function do() emulating the same functionality.
You want to pass the parameter by reference:
$var = "foo";
$unknown = "";
function foo($arg1, &$arg2) { // NOTE EXTRA "&"
$arg2 = "bar";
}
foo($var, $unknown);
echo $unknown;
See it in action.

PHP functions 101 question, really simple

I'm kind of slow in the head so can someone tell me why this isn't working:
function foo() {
$bar = 'hello world';
return $bar;
}
foo();
echo $bar;
I just want to return a value from a function and do something with it.
Because $bar does not exist outside of that function. Its scope is gone (function returned), so it is deallocated from memory.
You want echo foo();. This is because $bar is returned.
In your example, the $bar at the bottom lives in the same scope as foo(). $bar's value will be NULL (unless you have defined it above somewhere).
Your foo() function is returning, but you're not doing anything with it. Try this:
function foo() {
$bar = 'hello world';
return $bar;
}
echo foo();
// OR....
$bar = foo();
echo $bar;
You aren't storing the value returned by the foo function
Store the return value of the function in a variable
So
foo() should be replaced by
var $t = foo();
echo $t;
As the others have said, you must set a variable equal to foo() to do stuff with what foo() has returned.
i.e. $bar = foo();
You can do it the way you have it up there by having the variable passed by reference, like so:
function squareFoo(&$num) //The & before the variable name means it will be passed by reference, and is only done in the function declaration, rather than in the call.
{
$num *= $num;
}
$bar = 2;
echo $bar; //2
squareFoo($bar);
echo $bar; //4
squareFoo($bar);
echo $bar; //16
Passing by reference causes the function to use the original variable rather than creating a copy of it, and anything you do to the variable in the function will be done to the original variable.
Or, with your original example:
function foo(&$bar)
{
$bar = 'hello world';
}
$bar = 2;
echo $bar; //2
foo($bar);
echo $bar; //hello world

Categories