How to access the variable in inner function of outer function variable?
I want to access $arr variable in the inner function.
<?php
function outer() {
$arr = array();
function inner($val) {
global $arr;
if($val > 0) {
array_push($arr,$val);
}
}
inner(0);
inner(10);
inner(20);
print_r($arr);
}
outer();
codepad link
This kind of "inner function" does not do what you probably expect. The global(!) function inner() will be defined upon calling outer(). This also means, calling outer() twice results in a "cannot redefine inner()" error.
As #hindmost pointed out, you need closures, functions that can get access to variables of the current scope. Also, while normal functions cannot have a local scope, closures can, because they are stored as variables.
Your code with Closures:
function outer() {
$arr = array();
$inner = function($val) use (&$arr) {
if($val > 0) {
array_push($arr,$val);
}
}
$inner(0);
$inner(10);
$inner(20);
print_r($arr);
}
outer();
Edited your code. You may want to refer to this
function outer() {
$arr = array();
function inner(&$arr,$val) { // pass array by reference
if($val > 0) {
array_push($arr,$val);
}
}
inner($arr,0);
inner($arr,10);
inner($arr,20);
print_r($arr);
}
outer();
You can pass arr by value, but you will not be able to print this
Array
(
[0] => 10
[1] => 20
)
First, do not use functions inside functions. Why? Because with this you'll get fatal error when triggering outer function second time (and that is because second run will invoke inner function declaration once again).
Second, if you need to do something with function result (as it stands from your code) - return that value. That is what is function intended to do - return some value. Another option may be using reference as a parameter (like in sort() functions family) - but in normal situation you should avoid such behavior. This is side-effect and this makes code less readable in general.
Third, do not use global variables. Because this binds your functions to your context, making your code totally unpredictable in terms of changing global context - and also impossible to scale to other contexts.
Functions in php are all global.
If you want to access the global $arr, then you have to make it global too in outer function.
function outer() {
global $arr;
$arr = array();
function inner($val) {
global $arr;
if($val > 0) {
array_push($arr,$val);
}
}
inner(0);
inner(10);
inner(20);
print_r($arr);
}
outer();
There is an better way of doing this.
function outer() {
$arr = array();
$inner = function ($val) use (&$arr) {
if($val > 0) {
array_push($arr, $val);
}
};
$inner(0);
$inner(10);
$inner(20);
print_r($arr);
}
outer();
Just put global to the outer function.
function outer() {
global $arr;
$arr = array();
function inner($val) {
global $arr;
if($val > 0) {
array_push($arr,$val);
}
}
inner(0);
inner(10);
inner(20);
print_r($arr);
}
Updated codepad.
Related
I'm making a class that has several functions. There is one thing that makes me confused, which is when I call the function itself in its function:
in the following function, I don't get an error when I call the getChildKey function inside the function itself:
function getChildKey1($FPTree)
{
function getChildKey($FPTree){
$result = [];
if (isset($FPTree['child'])){
foreach ($FPTree['child'] as $key => $value){
$result[$key]=getChildKey($value);
}
}
if (empty($result)){
return 'gak ada array';
}
return $result;
}
$output = [];
foreach ($FPTree as $index => $child){
$output[$index]=getChildKey($child);
}
return $output;
}
and I get an error when I try to create a function similar to the getChildKey function, which calls the function itself in it:
function pathFinder($arr = [], $needle)
{
$path = '';
$paths = [];
foreach ($arr as $key => $value) {
if (is_array($value)) {
$path .= $key . "->";
pathFinder($value, $needle); //error here
} else {
if ($key === $needle) {
$paths[] = $path . $key;
}
}
}
return $paths; // return all found paths to key $needle
}
Why did it happen? what do I have to do so that the pathFinder function can call itself in it?
When you define a function, and call it that time (if function was found) php creates a scope which will be like a different "house" for all variables and functions that are declared/defined inside it. That's the reason we sometimes need to use the keyword global when we want to reference $var1 which is defined outside the function (and class if any) and we happen to have a variable with the same name declared in our function
CASE 1:
function A($args1)
{
//---- scope of A starts here
function B($args2)
{ return 'hello from B'; }
B(); // call B
//---- scope of A ends here
}
CASE 2:
function A($args1)
{
//---- scope of A starts here
A(); // call A
//but where is A?
//---- scope of A ends here
}
In 1st case the A function's block (anything between { }) is self-contained block meaning it has everything that any code inside it would need in order to run. So when B() is encountered php looks within the scope of A, whether any function named B is defined? Yes!
In 2nd case PHP does the same when it encounters A() but on not finding it there, it looks in the global scope ie. all code that is outside of your class to find a function named A. Since there isn't any it throws a not found exception
When you use $this->A() php knows where to look for this function ie.inside the same object where it was called from and it run perfectly
I try to find the solution since many hours, but I can't solve it (I'm not a programmer ;)).
On a function, I have set a dynamic array which I want to use in another function.
To do this, I thought to use $GLOBALS[] array
I have no problem to call the variable out of the function one, but when I try to use it in function 2, it doesn't works.
Here is my code :
function one($name,$a,$b,$c)
{
// $GLOBALS[${$name}] = array($a,$b,$c);
global $$name;
$$name = array($a,$b,$c);
}
function two($name)
{
$name="D1";
echo ${$name}[1];
}
one("D1",10,20,30);
one("D2",100,200,300);
two("D1"); // doesn't works
$name="D1";
echo ${$name}[1]; // works, gives 20
$name="D2";
echo ${$name}[1]; // works, gives 200
It doesn't works and I do not understand why.
Thanks for your help.
Etienne
how about doing something like this:
function one() {
$dynamicArray = generateDynamicArray();
return $dynamicArray;
}
function two() {
$one = one(); // if it's in a class use: $this->one();
foreach($one in $key=>$value) {
// your code for each item in the array we got form function one()
}
}
instead of defining it globally.
<?php
function one($name,$a,$b,$c)
{
global $$name;
$$name = array($a,$b,$c);
}
function two($name)
{
global $$name;
echo ${$name}[0];
}
one("D1",10,20,30);
two("D1");
The scope of your function is different to the global scope.
I have been given a API which I am currently back engineering. there is one function in particular that gives me troubles with fully understanding its purpose/use.
private function split($data, Callable $callback)
{
$split = array();
if ($data) {
$split = array_map(function($joined) use ($callback) {
return $callback(explode('::', $joined));
}, explode(',', $data));
}
return $split;
}
I dont fully understand the concept of Callable, and function within array_map, function($joined) then this function USE callable variable, Could someone explain this concept form me please
A Callable argument is an argument that you can call ! As you can see in the code, the argument $callback is used like a function: $callback(...)
This is called high-order programming and this is really useful in certain cases. A simple example: Let's say you have to code a function that adds 2 and another function that multiplies by 2 every elements of an array. A simple but verbose way to do that is:
function multiply($array) {
$results = array();
foreach ($array as $number) {
$results[] = $number * 2;
}
return $results;
}
function add($array) {
$results = array();
foreach ($array as $number) {
$results[] = $number + 2;
}
return $results;
}
A lot of code is the same in the 2 functions. High-order programming is useful in this case, what you can do is create a function apply($function, $array) that apply the function $function to all the elements of $array and returns an array with the result.
function apply($function, $array) {
$results = array();
foreach ($array as $number) {
$results[] = $function($number);
}
return $results;
}
Now, if you want to multiply all the elements by 2 or add 2, you simply do:
function multiply($array) {
return apply(function($number) {
return $number * 2;
}, $array);
}
function add($array) {
return apply(function($number) {
return $number + 2;
}, $array);
}
You see, we give a function as an argument to the apply function. This function (called $function in apply) is applied to all the elements of $array, and apply returns the results (called $results).
The PHP function array_map does exactly the same thing. When your code calls array_map, it gives a function that takes one argument (the element of the array to process) and returns the processed element (here, it simply applies the function $callback to it).
I was coding and I stumbled into this. Why doesn't this code work?
function remove($array,$key) {
unset($array[$key]);
}
function finished() {
$finished = array(1,2,3,4,5);
remove($finished,3);
return $finished;
}
http://codepad.org/vemXHwnA
This is because the array is copied (as it is passed by value). You need to pass by reference if you want to alter the original variable. Note the & in the parameter list of remove. It indicates that the parameter is passed by reference:
function remove(&$array,$key) {
unset($array[$key]);
}
function finished() {
$finished = array(1,2,3,4,5);
remove($finished, 3);
return $finished;
}
Demo
You need to return the array from your function as changing it in there does not affect the array in the global scope.
function remove($array,$key) {
unset($array[$key]); // $array is only changed inside the function
return $array;
}
$array = remove($array, 'key'); // now $array is changed
pass the reference of that variable using &
function remove(&$array,$key) {
unset($array[$key]);
}
I was wondering if i have a function like this:
function isAdmin ($user_id) {
$admin_arr = array(1, 2);
foreach ($admin_arr as $value) {
if ($value == $user_id) {
return true;
}
}
return false;
}
Could i make an array outside of that function as a global array and use it inside the function without sending it through as a parameter, also instead declaring a new admin array inside the function as i just did above? How would i do this?
Regards,
Alexander
To answer literal question:
// Global variable
$admin_arr = array(1, 2);
function isAdmin ($user_id) {
// Declare global
global $admin_arr;
foreach ($admin_arr as $value) {
if ($value == $user_id) {
return true;
}
}
return false;
}
Documentation here: http://php.net/manual/en/language.variables.scope.php
To answer the REAL question: Avoid global at all costs. You are introducing a plethora of error prone code into your application. Relying on global variables is entering a world of pain and makes your functions less useful.
Avoid it unless you absolutely see no other way.
you have to do this with the global keyword
here an example
$arr = array('bar');
function foo() {
global $arr;
echo array_pop($arr);
}
foo();
I concur with others that this is not the preferred way to do it, and you should be passing the array as a parameter, but I just wanted to point out the $GLOBALS[] superglobal array, which I find more readable than the global keyword.
$global_array = array(1,2,3);
function myfunc()
{
echo $GLOBALS['global_array'][0];
print_r($GLOBALS['global_array']);
}