3

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

kpmDev
  • 1,330
  • 1
  • 10
  • 28
  • 1
    You have to use `Closures` (http://www.php.net/manual/en/class.closure.php) – hindmost Mar 06 '14 at 08:02
  • Probably duplicate of [php - Callback function using variables calculated outside of it - Stack Overflow](https://stackoverflow.com/questions/4588714/callback-function-using-variables-calculated-outside-of-it) – user202729 Aug 15 '23 at 01:00

5 Answers5

12

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();
Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
6

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
)
Nuit
  • 106
  • 5
  • why does this and not @fab 's answer has so many upvotes although his approach is a lot cleaner? – thpl Mar 06 '14 at 08:09
1

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.

Alma Do
  • 37,009
  • 9
  • 76
  • 105
0

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();
xdazz
  • 158,678
  • 38
  • 247
  • 274
0

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.

aksu
  • 5,221
  • 5
  • 24
  • 39