PHP Function Variable Scope

Reference: What is variable scope, which variables are accessible from where and what are undefined variable errors?

What is "variable scope"?

Variables have a limited "scope", or "places from which they are accessible". Just because you wrote $foo = 'bar'; once somewhere in your application doesn't mean you can refer to $foo from everywhere else inside the application. The variable $foo has a certain scope within which it is valid and only code in the same scope has access to the variable.

How is a scope defined in PHP?

Very simple: PHP has function scope. That's the only kind of scope separator that exists in PHP. Variables inside a function are only available inside that function. Variables outside of functions are available anywhere outside of functions, but not inside any function. This means there's one special scope in PHP: the global scope. Any variable declared outside of any function is within this global scope.

Example:

<?php

$foo = 'bar';

function myFunc() {
$baz = 42;
}

$foo is in the global scope, $baz is in a local scope inside myFunc. Only code inside myFunc has access to $baz. Only code outside myFunc has access to $foo. Neither has access to the other:

<?php

$foo = 'bar';

function myFunc() {
$baz = 42;

echo $foo; // doesn't work
echo $baz; // works
}

echo $foo; // works
echo $baz; // doesn't work

Scope and included files

File boundaries do not separate scope:

a.php

<?php

$foo = 'bar';

b.php

<?php

include 'a.php';

echo $foo; // works!

The same rules apply to included code as applies to any other code: only functions separate scope. For the purpose of scope, you may think of including files like copy and pasting code:

c.php

<?php

function myFunc() {
include 'a.php';

echo $foo; // works
}

myFunc();

echo $foo; // doesn't work!

In the above example, a.php was included inside myFunc, any variables inside a.php only have local function scope. Just because they appear to be in the global scope in a.php doesn't necessarily mean they are, it actually depends on which context that code is included/executed in.

What about functions inside functions and classes?

Every new function declaration introduces a new scope, it's that simple.

(anonymous) functions inside functions

function foo() {
$foo = 'bar';

$bar = function () {
// no access to $foo
$baz = 'baz';
};

// no access to $baz
}

classes

$foo = 'foo';

class Bar {

public function baz() {
// no access to $foo
$baz = 'baz';
}

}

// no access to $baz

What is scope good for?

Dealing with scoping issues may seem annoying, but limited variable scope is essential to writing complex applications! If every variable you declare would be available from everywhere else inside your application, you'd be stepping all over your variables with no real way to track what changes what. There are only so many sensible names you can give to your variables, you probably want to use the variable "$name" in more than one place. If you could only have this unique variable name once in your app, you'd have to resort to really complicated naming schemes to make sure your variables are unique and that you're not changing the wrong variable from the wrong piece of code.

Observe:

function foo() {
echo $bar;
}

If there was no scope, what would the above function do? Where does $bar come from? What state does it have? Is it even initialized? Do you have to check every time? This is not maintainable. Which brings us to...

Crossing scope boundaries

The right way: passing variables in and out

function foo($bar) {
echo $bar;
return 42;
}

The variable $bar is explicitly coming into this scope as function argument. Just looking at this function it's clear where the values it works with originate from. It then explicitly returns a value. The caller has the confidence to know what variables the function will work with and where its return values come from:

$baz   = 'baz';
$blarg = foo($baz);

Extending the scope of variables into anonymous functions

$foo = 'bar';

$baz = function () use ($foo) {
echo $foo;
};

$baz();

The anonymous function explicitly includes $foo from its surrounding scope. Note that this is not the same as global scope.

The wrong way: global

As said before, the global scope is somewhat special, and functions can explicitly import variables from it:

$foo = 'bar';

function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}

This function uses and modifies the global variable $foo. Do not do this! (Unless you really really really really know what you're doing, and even then: don't!)

All the caller of this function sees is this:

baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!

There's no indication that this function has any side effects, yet it does. This very easily becomes a tangled mess as some functions keep modifying and requiring some global state. You want functions to be stateless, acting only on their inputs and returning defined output, however many times you call them.

You should avoid using the global scope in any way as much as possible; most certainly you should not be "pulling" variables out of the global scope into a local scope.

Access variable from function inside of nested function

You have two options:

  1. Give $content as a parameter

    function foo() {
    $content = 'foobar';

    function bar($content) {
    echo $content . '1'; // 'foobar1'
    }

    bar();
    }

    foo();
  2. Use closures (PHP Manual) (PHP 5.3.0+)

    Please note that the function declaration is a bit different compared to the 'conventional way' of declaring functions.

    function foo() {
    $content = 'foobar';

    $bar = function() use ($content) {
    echo $content . '1';
    }; // <-- As it's an assignment, end with a ';'

    $bar();
    }

    foo(); // 'foobar1'

php function variable scope

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.

PHP variable life cycle/ scope

In PHP control statements have no separate scope. They share the scope with the outer function or the global scope if no function is present. (PHP: Variable scope).

$foo = 'bar';

function foobar() {
$foo = 'baz';

// will output 'baz'
echo $foo;
}

// will output 'bar'
echo $foo;

Your variables will have the last value assigned within the control structure. It is good practice to initialize the variable before the control structure but it is not required.

// it is good practice to declare the variable before
// to avoid undefined variables. but it is not required.
$foo = 'bar';
if (true == false) {
$foo = 'baz';
}

// do something with $foo here

Namespaces do not affect variable scope. They only affect classes, interfaces, functions and constants (PHP: Namespaces Overview). The following code will output 'baz':

namespace A { 
$foo = 'bar';
}

namespace B {
// namespace does not affect variables
// so previous value is overwritten
$foo = 'baz';
}

namespace {
// prints 'baz'
echo $foo;
}

How can I define a local variable in a function in PHP?

function ha(){
global $user;
$user2 = 'abc'; // No prefix whatsoever

echo $user; // Prints global $user
echo $user2; // Prints local $user2
}

how can I define a static value of variable in PHP that is read from file config.php and only access the value in the function?

It's all about variable scope. If you want a variable to be defined in the configuration file and only be readable from within a function, then your current approach is incorrect.

Anything declared in the main scope (such as the configuration file loaded in the main scope) will be accessible from nearly anywhere in the code. If you don't want variables to be accessed otherwise than through ha() then they need to be defined within ha().

Why is external variable out of scope to PHP function?

in php if you want to use any variable inside any function without passing it in parameter. you need to defined it as global. it before using you need global $dbConnect.

<?php
//constants for database connection
define(DB_RESOURCE, "192.168.99.67");
define(DB_USERNAME, "myUsername");
define(DB_PASSWORD, "p@ssword");
define(DB_NAME, "myDatabase");
//variable defined here so why can't function see it?
$dbConnect = mysqli_connect(DB_RESOURCE, DB_USERNAME, DB_PASSWORD, DB_NAME);

function readData($table, $column) {
$sql = "SELECT {$column} FROM {table}";
//redefining this solves the problem but why is this needed?
global $dbConnect;
// now you can use $dbConnect. In php you need to specify it as global once inside the block after it you can use

$data = mysqli_query($dbConnect, $sql);
}
?>

PHP function use variable from outside

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:

  • Variable scope in PHP
  • Anonymous functions


Related Topics



Leave a reply



Submit