62
function parts($part) { 
    $structure = 'http://' . $site_url . 'content/'; 
    echo($tructure . $part . '.php'); 
}

This function uses a variable $site_url that was defined at the top of this page, but this variable is not being passed into the function.

How do we get it to return in the function?

stakx - no longer contributing
  • 77,057
  • 17
  • 151
  • 248
RIK
  • 17,723
  • 34
  • 107
  • 185

5 Answers5

136

Add second parameter

You need to pass additional parameter to your function:

function parts($site_url, $part) { 
    $structure = 'http://' . $site_url . 'content/'; 
    echo $structure . $part . '.php'; 
}

In case of closures

If you'd rather use closures then you can import variable to the current scope (the use keyword):

$parts = function($part) use ($site_url) { 
    $structure = 'http://' . $site_url . 'content/'; 
    echo $structure . $part . '.php'; 
};

global - a bad practice

This post is frequently read, so something needs to be clarified about global. Using it is considered a bad practice (refer to this and this).

For the completeness sake here is the solution using global:

function parts($part) { 
    global $site_url;
    $structure = 'http://' . $site_url . 'content/'; 
    echo($structure . $part . '.php'); 
}

It works because you have to tell interpreter that you want to use a global variable, now it thinks it's a local variable (within your function).

Suggested reading:

Anthony Hatzopoulos
  • 9,929
  • 2
  • 35
  • 56
Zbigniew
  • 25,495
  • 6
  • 53
  • 63
  • The adding a second or more parameter is not always the most practical thing. It simply increases the number of arguments we have to pass every time we are calling a function, in my case where I am building a function that works on strings and is repeated multiple times throughout the page it is very difficult to make it this way, – Deepak Kamat Nov 13 '19 at 19:02
  • Also adding a second parameter may not always be possible, for example with array_filter() or similar cases where you cannot influence the caller. – BlaM Nov 13 '20 at 13:05
44

Alternatively, you can bring variables in from the outside scope by using closures with the use keyword.

$myVar = "foo";
$myFunction = function($arg1, $arg2) use ($myVar)
{
 return $arg1 . $myVar . $arg2;
};
Joe Green
  • 1,685
  • 1
  • 12
  • 17
  • 2
    This way is a little hard, for example if you have 10 variable this way will be hard. – Mohammad Kermani May 10 '14 at 08:09
  • 1
    php shows error, why? Parse error: syntax error, unexpected 'use' (T_USE), expecting '{' – Mohammad Kermani May 10 '14 at 08:12
  • 1
    @Kermani you are probably using an older version of PHP which does not have the `use` syntax. This syntax was introduced in PHP5.3. See https://wiki.php.net/rfc/closures – Joe Green Sep 11 '14 at 13:52
  • @JoeGreen, what is this functionality known as to be able to use the variables that are defined outside of function. – Gunnrryy Aug 01 '17 at 10:03
  • @Gunnrryy look up closures and scope – Joe Green Aug 01 '17 at 16:30
  • 2
    @thiout_p I think it's too late to answer. but maybe somebody else is seeking the answer: closures are defined in variables and has no names $myFunction = function myFunction() this is a wrong syntax. and using lexical variables is not possible. the right syntax is **$myFunction = function()** then lexical variables would be allowed. to call the closure $myFunction() – pixxet Nov 27 '18 at 06:41
7

Do not forget that you also can pass these use variables by reference.

The use cases are when you need to change the use'd variable from inside of your callback (e.g. produce the new array of different objects from some source array of objects).

$sourcearray = [ (object) ['a' => 1], (object) ['a' => 2]];
$newarray = [];
array_walk($sourcearray, function ($item) use (&$newarray) {
    $newarray[] = (object) ['times2' => $item->a * 2];
});
var_dump($newarray);

Now $newarray will comprise (pseudocode here for brevity) [{times2:2},{times2:4}].

On the contrary, using $newarray with no & modifier would make outer $newarray variable be read-only accessible from within the closure scope. But $newarray within closure scope would be a completelly different newly created variable living only within the closure scope.

Despite both variables' names are the same these would be two different variables. The outer $newarray variable would comprise [] in this case after the code has finishes.

Valentine Shi
  • 3,093
  • 2
  • 25
  • 35
  • 1
    This method fixed my (different) problem where updating the variable being used from the outer scope wouldn't be reflected within the function. Referring to it by reference would allow me to get the value at that point in time from the outer scope. – Alex W May 09 '19 at 23:44
0

Just put in the function using GLOBAL keyword:

 global $site_url;
TarangP
  • 2,560
  • 5
  • 18
  • 35
HBv6
  • 3,389
  • 4
  • 26
  • 41
0

I suppose this depends on your architecture and whatever else you may need to consider, but you could also take the object-oriented approach and use a class.

class ClassName {

    private $site_url;

    function __construct( $url ) {
        $this->site_url = $url;
    }

    public function parts( string $part ) {
        echo 'http://' . $this->site_url . 'content/' . $part . '.php';
    }

    # You could build a bunch of other things here
    # too and still have access to $this->site_url.
}

Then you can create and use the object wherever you'd like.

$obj = new ClassName($site_url);
$obj->parts('part_argument');

This could be overkill for what OP was specifically trying to achieve, but it's at least an option I wanted to put on the table for newcomers since nobody mentioned it yet.

The advantage here is scalability and containment. For example, if you find yourself needing to pass the same variables as references to multiple functions for the sake of a common task, that could be an indicator that a class is in order.

Leon Williams
  • 466
  • 1
  • 6
  • 15