PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Переменные переменные> <Предопределенные переменные
Last updated: Fri, 26 Sep 2008

view this page in

Область видимости переменной

Область видимости переменной - это среда, в которой она определена. В большинстве случаев все переменные PHP имеют единую область видимости. Эта единая область видимости охватывает также включаемые (include) и требуемые (require) файлы. Например:

<?php
$a 
1;
include 
"b.inc";
?>

Здесь переменная $a будет доступна внутри включенного скрипта b.inc. Однако, внутри определенных пользователем функций вводится локальная область видимости функции. Любая, используемая внутри функции переменная, по умолчанию ограничена локальной областью видимости функции. Например:

<?php
$a 
1/* глобальная область видимости */ 

function Test()

    echo 
$a/* ссылка на переменную локальной области видимости */ 


Test();
?>

Этот скрипт не сгенерирует никакого вывода, поскольку выражение echo указывает на локальную версию переменной $a, а в пределах этой области видимости ей не не было присвоено значение. Возможно вы заметили, что это немного отличается от языка C в том, что глобальные переменные в C автоматически доступны функциям, если только они не были перезаписаны локальным определением. Это может вызвать некоторые проблемы, поскольку люди могут нечаянно изменить глобальную переменную. В PHP, если глобальная переменная будет использоваться внутри функции, она должна быть объявлена глобальной внутри нее.

Ключевое слово global

Сначала пример использования global:

Пример #1 Использование global

<?php
$a 
1;
$b 2;

function 
Sum()
{
    global 
$a$b;

    
$b $a $b;


Sum();
echo 
$b;
?>

Вышеприведенный скрипт выведет "3". После определения $a и $b внутри функции как global все ссылки на любую из этих переменных будут указывать на их глобальную версию. Не существует никаких ограничений на количество глобальных переменных, которые могут обрабатываться функцией.

Второй способ доступа к переменным глобальной области видимости - использование специального, определяемого PHP массива $GLOBALS. Предыдущий пример может быть переписан так:

Пример #2 Использование $GLOBALS вместо global

<?php
$a 
1;
$b 2;

function 
Sum()
{
    
$GLOBALS["b"] = $GLOBALS["a"] + $GLOBALS["b"];


Sum();
echo 
$b;
?>

$GLOBALS - это ассоциативный массив, ключом которого является имя, а значением - содержимое глобальной переменной. Обратите внимание, что $GLOBALS существует в любой области видимости, это объясняется тем, что этот массив является суперглобальным. Ниже приведен пример, демонстрирующий возможности суперглобальных переменных:

Пример #3 Суперглобальные переменные и область видимости

<?php
function test_global()
{
    
// Большинство предопределенных переменных не являются
    // "супер" и чтобы быть доступными в локальной области
    // видимости функции требуют указания 'global'.
    
global $HTTP_POST_VARS;
    
    echo 
$HTTP_POST_VARS['name'];
    
    
// Суперглобальные переменные доступны в любой области
    // видимости и не требуют указания 'global'.
    // Суперглобальные переменные доступны, начиная с PHP 4.1.0
    
echo $_POST['name'];
}
?>

Использование статических переменных

Другой важной возможностью области видимости переменной является статическая переменная. Статическая переменная существует только в локальной области видимости функции, но не теряет своего значения, когда выполнение программы выходит из этой области видимости. Рассмотрим следующий пример:

Пример #4 Демонстрация необходимости статических переменных

<?php
function Test ()
{
    
$a 0;
    echo 
$a;
    
$a++;
}
?>

Эта функция абсолютно бесполезна поскольку при каждом вызове она устанавливает $a в 0 и выводит "0". Инкремент переменной $a++ здесь не играет роли, так как при выходе из функции переменная $a исчезает. Чтобы написать полезную считающую функцию, которая не будет терять текущего значения счетчика, переменная $a объявляется как static:

Пример #5 Пример использования статических переменных

<?php
function Test()
{
    static 
$a 0;
    echo 
$a;
    
$a++;
}
?>

Теперь при каждом вызове функция Test() будет выводить значение $a и инкрементировать его.

Статические переменные также дают возможность работать с рекурсивными функциями. Рекурсивной является функция, вызывающая саму себя. При написании рекурсивной функции нужно быть внимательным, поскольку есть вероятность сделать рекурсию бесконечной. Вы должны убедиться, что существует адекватный способ завершения рекурсии. Следующая простая функция рекурсивно считает до 10, используя для определения момента остановки статическую переменную $count:

Пример #6 Статические переменные и рекурсивные функции

<?php
function Test()
{
    static 
$count 0;

    
$count++;
    echo 
$count;
    if (
$count 10) {
        
Test ();
    }
    
$count--;
}
?>

Замечание: Статические переменные могут быть объявлены так, как показано в предыдущем примере. Попытка присвоить этим переменным значения, являющиеся результатом выражений, вызовет ошибку обработки.

Пример #7 Объявление статических переменных

<?php
function foo(){
    static 
$int 0;          // верно
    
static $int 1+2;        // неверно  (поскольку это выражение)
    
static $int sqrt(121);  // неверно  (поскольку это тоже выражение)

    
$int++;
    echo 
$int;
}
?>

Ссылки с глобальными и статическими переменными

Движок Zend 1, лежащий в основе PHP 4, оперирует модификаторами переменных static и global как ссылками. Например, реальная глобальная переменная, внедренная в область видимости функции указанием ключевого слова global, в действительности создает ссылку на глобальную переменную. Это может привести к неожиданному поведению, как это показано в следующем примере:

<?php
function test_global_ref() {
    global 
$obj;
    
$obj = &new stdclass;
}

function 
test_global_noref() {
    global 
$obj;
    
$obj = new stdclass;
}

test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>

Выполнение этого примера сгенерирует следующий вывод:

NULL
object(stdClass)(0) {
}
   

Аналогично ведет себя и выражение static. Ссылки не хранятся статично:

<?php
function &get_instance_ref() {
    static 
$obj;

    echo 
"Static object: ";
    
var_dump($obj);
    if (!isset(
$obj)) {
        
// Присвоить ссылку статической переменной
        
$obj = &new stdclass;
    }
    
$obj->property++;
    return 
$obj;
}

function &
get_instance_noref() {
    static 
$obj;

    echo 
"Static object: ";
    
var_dump($obj);
    if (!isset(
$obj)) {
        
// Присвоить объект статической переменной
        
$obj = new stdclass;
    }
    
$obj->property++;
    return 
$obj;
}

$obj1 get_instance_ref();
$still_obj1 get_instance_ref();
echo 
"\n";
$obj2 get_instance_noref();
$still_obj2 get_instance_noref();
?>

Выполнение этого примера сгенерирует следующий вывод:

Static object: NULL
Static object: NULL

Static object: NULL
Static object: object(stdClass)(1) {
  ["property"]=>
  int(1)
}
   

Этот пример демонстрирует, что при присвоении ссылки статической переменной она не запоминается, когда вы вызываете функцию &get_instance_ref() во второй раз.



add a note add a note User Contributed Notes
Область видимости переменной
ddarjany at yahoo dot com
19-Aug-2008 09:15
Note that if you declare a variable in a function, then set it as global in that function, its value will not be retained outside of that function.  This was tripping me up for a while so I thought it would be worth noting.

<?PHP

foo
();
echo
$a; // echoes nothing

bar();
echo
$b; //echoes "b";

function foo() {
 
$a = "a";
  global
$a;
}

function
bar() {
  global
$b;
 
$b = "b";
}

?>
lgrk
28-May-2008 07:41
Useful function:
<?php
function cycle($a, $b, $i=0) {
    static
$switches = array();
    if (isset(
$switches[$i])) $switches[$i] = !$switches[$i]; else !$switches[$i] = true;
    return (
$switches[$i])?$a:$b;
}
?>

Exeample

<?php
for ($i = 1; $i<3; $i++) {
    echo
$i.cycle('a', 'b').PHP_EOL;
    for (
$j = 1; $j<5; $j++) {
        echo
' '.$j.cycle('a', 'b', 1).PHP_EOL;
        for (
$k = 1; $k<3; $k++) {
            echo
'  '.$k.cycle('c', 'd', 2).PHP_EOL;
        }
    }
}
/**
Output:
1a
 1a
  1c
  2d
 2b
  1c
  2d
 3a
  1c
  2d
 4b
  1c
  2d
2b
 1a
  1c
  2d
 2b
  1c
  2d
 3a
  1c
  2d
 4b
  1c
  2d
*/

?>
tomodachi
30-Mar-2008 06:16
@ben writes:
eval('global $' . join(',$', array_keys($GLOBALS)) . ';');

You may find extract($GLOBALS) useful. (also, note the optional EXTR_REFS flag)
ben FROM THE SITE younevercall.com
19-Mar-2008 03:40
To make all globals available in a function:

eval('global $' . join(',$', array_keys($GLOBALS)) . ';');

Use with caution. "eval" is inherently dangerous.
Thomas
04-Mar-2008 03:06
It might be worth noting in the article that you shouldn't define magic values at global level and use "global" to access them in a function - like I did in the past few years.

Use define() instead.
Anonymous
01-Mar-2008 12:10
I was pondering a little something regarding caching classes within a function in order to prevent the need to initiate them multiple times and not clutter the caching function's class properties with more values.

I came here because I remembered something about references being lost. So I made a test to see if I could pull what I wanted to off anyway. Here's and example of how to get around the references lost issue. I hope it is helpful to someone else!

<?php
class test1{}
class
test2{}
class
test3{}

function
cache( $class )
{
    static
$loaders = array();
   
   
$loaders[ $class ] = new $class();

   
var_dump( $loaders );
}
print
'<pre>';
cache( 'test1' );
cache( 'test2' );
cache( 'test3' );

?>
kevin at metalaxe dot com
01-Mar-2008 11:56
in reply to: "I hope some1 reading and understanding here creates an example about this. Im so lazy at doing that." -- pepesantillan at gmail dot com

Though not exactly your example, I don't like functions declared within functions. So this is, effectively, the same result you were explaining :P

<?php
ini_set
( 'display_errors', true );
error_reporting( E_ALL | E_STRICT );
/**
* This is already in the global scope
**/
$global_var1 = 'I\'m global!';

// Call a function
some_function();

//Note that $localvar is NOT in the global scope
//Undefined variable Error
var_dump( $localvar );

function
some_function()
{
   
/**
    * Now we are in function scope. Global scope vars can't be accessed here
    **/

    // Undefined variable error (for $global_var1)
   
$localvar = $global_var1;

   
//Gonna call another function and send $localvar as ref
   
another_function( $localvar );

   
// Note that $localvar has a value here...
   
var_dump( $localvar );
}

function
another_function( &$input )
{
   
// Get the global
   
global $global_var1;

   
// Assign it to $input which is referenced to $localvar in the other function
   
$input = $global_var1;
}
?>
Jeremy Skellington
30-Jan-2008 01:14
Hmm, globals are a pretty poor solution and are pretty much forbidden in object oriented programming.
pepesantillan at gmail dot com
20-Dec-2007 07:36
allan on 12-Sep-2006 10:53 wrote:
Using the global keyword inside a function to define a variable is essentially the same as passing the variable by reference as a parameter:

somefunction(){
   global $var;
}

is the same as:

somefunction(& $a) {

}

The advantage to using the keyword is if you have a long list of variables  needed by the function - you dont have to pass them every time you call the function.

---------------------------------------------------------------

Just wanted to point out that using global and using a reference is NOT the same. Why?

Imagine you just called the function somefunction() defined by out friend here from another function, say otherfunction().

If you use the global example (the 1st one), you will create a global variable $var for your whole php script.

But if you use the 2nd example where you reference a variable, you could be ONLY changing the value of some variable in the function that called the function somefunction() - in this case otherfunction() - and not creating a new global variable for your whole php script.

I hope some1 reading and understanding here creates an example about this. Im so lazy at doing that.

Hope you got the idea, and have as much fun learning to use php as I am! (yay! variables variables tutorial is next! xD)
jistanidiot at gmail dot com
19-Dec-2007 11:42
Beware the problem that davo971 AT gmail DOT NO DAMN SPAM COM demonstrates can also happen in the following case:

index.php
<?php

include("test.inc");

?>

test.inc
<?php

function foo() {
    global
$bar;

    echo
$bar;

}

$bar = "Hello World";
foo();

?>

This prints nothing. 

if you add global $bar  at the start of test.inc it will work just fine.
SID TRIVEDI
27-Oct-2007 03:46
<?php
/*
VARIABLE SCOPE : GLOBAL V/S STATIC

If variable $count is defined global as under, instead of static, it does not work well as desired in repeated function calls.

$count = 1; //if not defined STATIC, in each function call, it starts countig from one to 25.
global $count;

which gives folowing output:
0123456789101112131415161718192021222324
Total 24 numbers are printed.
So far 26 function call(s) made.

26272829303132333435363738394041424344454647484950
Total 50 numbers are printed.
So far 52 function call(s) made.
*/

function print_1to50()
{
//    $count = 1;
//    global $count;
   
static $count=1; // Initial assigment of One to $count, static declarion holds the last(previous) value of variable $count in each next function calls.
       
$limit = $count+24;
        while(
$count<=$limit)
        {
        echo
"$count";
       
$count=$count+1;
        }
       
$num_count= $count-1;
        echo
"<br>\n". "Total $num_count numbers are printed.<br>";

        return;
// return statement without parenthesis()or arguments denotes end of a function rather than returning any values to subsequent function call(s).
} // end of while loop

$count=0;
print_1to50();
$count=$count+1;
print
"So far $count function call(s) made.<br><br>";

print_1to50();
$count=$count+1;
print
"So far $count function call(s) made.<br>";
/*
Which gives following output:
12345678910111213141516171819202122232425
Now I have printed 25 numbers.
I have made 1 function call(s).
26272829303132333435363738394041424344454647484950
Now I have printed 50 numbers.
I have made 2 function call(s).
*/

?>
daniel at nohair dot com
09-Sep-2007 02:01
Ah, nested functions.  Thanks for your notes below, search on  page for "nested functions" folks.   This is how this seems to work.

The child function is seen at global level only after they have been seen once.  But, variables inside functions are only reachable within the functions scope.

<?php
$var1
= "This is \$var1 OUTSIDE parent function <br />";
function
parent_function() {
    echo
"Now inside parent <br />";
   
$var1 = "This is \$var1 INSIDE parent function <br />";
   
$var2 = "This is \$var2 INSIDE parent function <br />";
    function
child_function() {
        echo
"now inside child <br />";
       
//global $var1; //Calls var1 outside parent_function;
       
echo $var1; //doesn't work without global;
        // even if we comment out $var1 outside parent function.
        // global $var1 doesn't reach the one inside parent function.
       
echo $var2; //doesn't work; Can't seem to reach parent variables.
   
}
    echo
"Now calling child<br />";
   
//child_function();    //works
}

// child_function(); //causes fatal error: call to undefined function;
parent_function();  //works;
child_function(); //now works;

?>
crack wilding
24-Aug-2007 09:04
Another way of dealing with a large number of globals is to declare a single global array and then put all your global variables into it. Like this:

$_G = array(
    'foo' => 'some text',
    'bar' => 4,
    'boo' => 'more text,
    'far' => 'yet more text'
);

Now you just declare the one global array in each function:

function blah() {
    global $_G;
    echo $_G['foo']; // or whatever
}

You can freely add to it without having to go back and add variable declarations to your functions. Kinda like using the $GLOBALS superglobal, except you don't have to  type so much.
mod
14-Mar-2007 01:03
Can not access to global variables from destructor, if obj is not unseted at the end:

<?php

 
class A
  
{
     function
__destruct()
      {
        global
$g_Obj;
        echo
"<br>#step 2: ";
       
var_dump($g_Obj);
      }

     function
start()
      {
        global
$g_Obj;
        echo
"<br>#step 1: ";
       
var_dump($g_Obj);
      }
   };

 
$g_Obj = new A();        // start here
 
$g_Obj->start();
 
$g_Obj = NULL;        // !!! comment line and result will changed !!!

?>

Result, if line is not commented:

#step 1: object(A)#1 (0) { }
#step 2: object(A)#1 (0) { }

Result, if line is commented:

#step 1: object(A)#1 (0) { }
#step 2: NULL
12-Mar-2007 02:13
addendum to warhog at warhog dot net
about static variables within methods
<?php

class A
{
    function
incStaticVar()
    {
        static
$var = 0;
       
$var++;
        return
$var;
    }
}

class
B extends A
{
}

$a =& new A();
$b =& new B();

print_r(array(
   
$a->incStaticVar(),
   
$b->incStaticVar(),
   
$a->incStaticVar(),
));

?>

expected result
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)

real result
Array
(
    [0] => 1
    [1] => 1
    [2] => 2
)

So I conclude that the PHP5 duplicates methods for each inherited classes.
Rohan
25-Jan-2007 11:11
<?php
$a
= 20;
function
myfunction($b){
   
$a=30;   //Local Variable
   
global $a,$c; //here global $a overrides the local
   
return $c=($b+$a);
}
print
myfunction(40)+$c;
?>

The output of this function will be 120.
Michael
07-Nov-2006 11:35
davo971 (http://us2.php.net/manual/en/language.variables.scope.php#69765), it seems you're encountering the same mental block that jason (http://us2.php.net/manual/en/language.variables.scope.php#65337) was having.  I know how that goes, because I used to have this problem as well.  Don't think of permission to access a variable as being transferred from function to function.  There is exactly 1 global scope in any script, and that's the scope outside of all functions and classes.  If you specify a variable as global, it does not mean you are accessing a variable in the calling function's namespace, it means you are accessing the variable in the global namespace.  In your example, you seemed to think that declaring $new_var global in function2() would give it access to variables declared in function1()'s namespace.  In fact, acess to variables does not propagate up the function stack--declaring you wish to work on a global variable ALWAYS gives you access to the SINGLE variable declared in the global namespace with that name.  It's more easily understood when you work with the $GLOBALS array... there's only 1 such array, and consequently there's exactly 1 of each global variable.  So if we modify your example to work correctly, here's what it'll look like:

<?php
$var
= 'foo';
$new_var = 'asdf';

function
function1()
{
   global
$new_var; //Now working with global $new_var, declared above
  
$new_var = 'bar'; //Changing $new_var from 'asdf' to 'bar'
  
function2();
}

function
function2()
{
   global
$var, $new_var; //Accessing global variables $var and $new_var, declared outside any functions
  
echo($var . $new_var);
}

function1();
?>

Outputs foobar
davo971 AT gmail DOT NO DAMN SPAM COM
19-Sep-2006 11:17
Be careful, come across this a lot.

<?php
$var
= 'foo';

function
function1()
{
    global
$var;
   
$new_var = 'bar';
   
function2();
}

function
function2()
{
    global
$var, $new_var;
    echo(
$var . $new_var);
}

function1();

?>

Outputs foo not foobar.
alan
12-Sep-2006 11:53
Using the global keyword inside a function to define a variable is essentially the same as passing the variable by reference as a parameter:

somefunction(){
   global $var;
}

is the same as:

somefunction(& $a) {

}

The advantage to using the keyword is if you have a long list of variables  needed by the function - you dont have to pass them every time you call the function.
mega-squall at caramail dot com
22-Jul-2006 09:47
In addition to sami's comment :

`static` keyword for class method is considered a compatibility feature in PHP5. In PHP6 however, calling an instance method (not defined using `static`) as a class method (using `class::method()` ) will display an EWarning. Also note that in PHP6, calling a class method (defined using `static`) as an instance method (using `$instance->method()`) will ALSO display an EWarning.
sami doesn't want spam at no-eff-eks com
21-Jul-2006 10:18
PHP 5.1.4 doesn't seem to care about the static keyword. It doesn't let you use $this in a static method, but you can call class methods through an instance of the class using regular -> notation. You can also call instance methods as class methods through the class itself. The documentiation here is plain wrong.

class Foo {
  public static function static_fun()
  {
    return "This is a class method!\n";
  }
 
  public function not_static_fun()
  {
    return "This is an instance method!\n";
  }
}

echo '<pre>';
echo "From Foo:\n";
echo Foo::static_fun();
echo Foo::not_static_fun();
echo "\n";

echo "From \$foo = new Foo():\n";
$foo = new Foo();
echo $foo->static_fun();
echo $foo->not_static_fun();
echo '</pre>';

You'll see the following output:

From Foo:
This is a class method!
This is an instance method!

From $foo = new Foo():
This is a class method!
This is an instance method!
variable_scope-php dot net at fijiwebdesign dot com
06-Jul-2006 08:48
In response to: Variable scope

Quote: "the global keyword *will* allow you to access variables in the global scope of your script, even if those variables were not made available locally to the parent function."

Actually, the "parent" function does not access a variable in its global scope unless it specifically uses the global modifier on the variable.

See this test:

<?php

$var
= ''; // global scope
function foo() {
   
$var = 'Hello from $foo';
   
bar();
    echo
$var;
}

function
bar() {
    global
$var;
   
$var = 'Hello from $var';
}

foo(); // prints: "Hello from $foo"

?>

The global scope of the variable $var is only available to bar(), not to foo(). Even if you were to put foo() and bar() in the same parent class, this would still be the case.
jason
28-Apr-2006 04:53
This is probably self-evident to most folks here, and I expected this behavior, but it wasn't explicitly mentioned in the manual itself so I tested to find out: the global keyword *will* allow you to access variables in the global scope of your script, even if those variables were not made available locally to the parent function.  In other words, the following will work as expected, even though $a is never referenced as global within the function foo:

<?php

function foo() {
   
bar();
}

function
bar() {
    global
$a;
    echo
$a;
}

$a = "works!";
foo();

?>
Rhett
03-Apr-2006 02:37
You could get around that:

<?php
function someFunction () {
   static
$isInitialized = 0;
   static
$otherStatic = 0; // or whatever default you want

  
if (!$isInitialized) {
     
$otherStatic = function(); // or whatever
     
$isInitialized = 1;
   }
   ...
}
?>

Needs an extra variable and evaluates a condition every time it's run, but it does get around your problem.
SasQ
31-Mar-2006 02:02
<?php
I
use PHP 4.3 and it's impossible to assign a variable or function result to a static variable :-(  Example:

function SomeFunction()
{
 $LocalVar = 5;
 static $MyStaticVar1 = some_function();  //ERROR
 static $MyStaticVar2 = $LocalVar            //ERROR
 static $MyStaticVar3 = 7;                       //OK
 return $MyStaticVar3++;
}

It'
s a little annoying, because in some cases the value of static variables aren't necessarily known at the moment of their initialisation. And sometimes it's required to be a value returned by some function or a value of some other function created earlier. Unfortunately, the moment of the initialization is the only moment, when this kind of assignment is possible to execute only on the first time the function is called.
?>
larax at o2 dot pl
22-Mar-2006 04:38
About more complex situation using global variables..

Let's say we have two files:
a.php
<?php
   
function a() {
        include(
"b.php");
    }
   
a();
?>

b.php
<?php
    $b
= "something";
    function
b() {
        global
$b;
       
$b = "something new";
    }
   
b();
    echo
$b;
?>

You could expect that this script will return "something new" but no, it will return "something". To make it working properly, you must add global keyword in $b definition, in above example it will be:

global $b;
$b = "something";
franp at free dot fr
10-Feb-2006 05:25
If you want to access a table row using $GLOBALS, you must do it outside string delimiters or using curl braces :

$siteParams["siteName"] = "myweb";

function foo() {
$table = $GLOBALS["siteParams"]["siteName"]."articles";  // OK
echo $table; // output  "mywebarticles"
$table = "{$GLOBALS["siteParams"]["siteName"]}articles"; // OK
echo $table; // output  "mywebarticles"
$table = "$GLOBALS[siteParams][siteName]articles";       // Not OK
echo $table; // output  "Array[siteName]article"

$result = mysql_query("UPDATE $table ...");
}

Or use global :

function foo() {
global $siteParams;
$table = "$siteParams[siteName]articles";         // OK
echo $table; // output  "mywebarticles"

$result = mysql_query("UPDATE $table ...");
}
marcin
30-Dec-2005 10:07
Sometimes in PHP 4 you need static variabiles in class. You can do it by referencing static variable in constructor to the class variable:

<?php
class test  {

   var
$var;
   var
$static_var;
    function
test()
    {
        static
$s;
       
$this->static_var =& $s;
    }
 
}

 
$a=new test();

 
$a->static_var=4;
 
$a->var=4;
 
 
$b=new test();
 
 echo
$b->static_var; //this will output 4
 
echo $b->var; //this will output nul
?>
warhog at warhog dot net
13-Dec-2005 01:22
Some interesting behavior (tested with PHP5), using the static-scope-keyword inside of class-methods.

<?php

class sample_class
{
  public function
func_having_static_var($x = NULL)
  {
    static
$var = 0;
    if (
$x === NULL)
    { return
$var; }
   
$var = $x;
  }
}

$a = new sample_class();
$b = new sample_class();

echo
$a->func_having_static_var()."\n";
echo
$b->func_having_static_var()."\n";
// this will output (as expected):
//  0
//  0

$a->func_having_static_var(3);

echo
$a->func_having_static_var()."\n";
echo
$b->func_having_static_var()."\n";
// this will output:
//  3
//  3
// maybe you expected:
//  3
//  0

?>

One could expect "3 0" to be outputted, as you might think that $a->func_having_static_var(3); only alters the value of the static $var of the function "in" $a - but as the name says, these are class-methods. Having an object is just a collection of properties, the functions remain at the class. So if you declare a variable as static inside a function, it's static for the whole class and all of its instances, not for each object.

Maybe it's senseless to post that.. cause if you want to have the behaviour that I expected, you can simply use a variable of the object itself:

<?php
class sample_class
{ protected $var = 0;
  function
func($x = NULL)
  {
$this->var = $x; }
}
?>

I believe that all normal-thinking people would never even try to make this work with the static-keyword, for those who try (like me), this note maybe helpfull.
zapakh at yahoo dot com
31-Oct-2005 09:23
Addendum to the post by tc underline at gmx TLD ch, on unsetting global variables from inside functions:

If setting to null is not a suitable substitute for unset() in your application, you can unset the global variable's entry in the $GLOBALS superglobal.

<?php
function testc()
{
  global
$a;
  echo
"  inner testc: $a\n";
  unset(
$GLOBALS['a']);
  echo
"  inner testc: $a\n";
}

$a = 5678;
echo
"<pre>";
echo
"outer: $a\n";
testc();
echo
"outer: $a\n";
echo
"</pre>\n";
?>

/***** Output:
outer: 5678
  inner testc: 5678
  inner testc: 5678
outer:
******/

If the behavior of testc (or testa or testb, for that matter) seems surprising, consider that the use of the 'global' keyword simply performs an assignment by reference.  In other words,

<?php
 
global $a;              //these two lines
 
$a =& $GLOBALS['a'];    //are equivalent.
?>

If you've read http://php.net/references , then everything behaves as you'd expect.
tc underline at gmx TLD ch
14-Sep-2005 04:06
Pay attention while unsetting variables inside functions:

<?php
$a
= "1234";
echo
"<pre>";
echo
"outer: $a\n";
function
testa()
{
    global
$a;
    echo
"   inner testa: $a\n";
    unset (
$a);
    echo
"   inner testa: $a\n";
}
function
testb()
{
    global
$a;
    echo
"   inner testb: $a\n";
   
$a = null;
    echo
"   inner testb: $a\n";
}
testa();
echo
"outer: $a\n";
testb();
echo
"outer: $a\n";
echo
"</pre>";
?>

/***** Result:
outer: 1234
   inner testa: 1234
   inner testa:
outer: 1234
   inner testb: 1234
   inner testb:
outer:
******/

Took me 1 hour to find out why my variable was still there after unsetting it ...

Thomas Candrian
thomas at pixtur dot de
08-Aug-2005 09:02
Be careful with "require", "require_once" and "include" inside functions. Even if the included file seems to define global variables, they might not be defined as such.

consider those two files:

---index.php------------------------------
function foo() {
 require_once("class_person.inc");

 $person= new Person();
 echo $person->my_flag; // should be true, but is undefined
}

foo();

---class_person.inc----------------------------
$seems_global=true;

class Person {
  public $my_flag;

 public function  __construct() {
   global $seems_global;
   $my_flag= $seems_global
 }
}

---------------------------------

The reason for this behavior is quiet obvious, once you figured it out. Sadly this might not be always as easy as in this example. A solution  would be to add the line...

global $seems_global;

at the beginning of "class_person.inc". That makes sure you set the global-var.

   best regards
    tom

ps: bug search time approx. 1 hour.
www dot php dot net dot 2nd at mailfilter dot com dot ar
17-Jul-2005 07:43
To the bemused poster: Of course you can't compare processing times between functions/no functions. I only wanted to see the difference between referenced and copied variables in different scenarios. Tests are only meant to compare between pairs (i.e., call a function with & and call the same function without &). I did 4 individual pairs of tests, so test 1 compares to test 2, test 3 compares to test 4, test 5 compares to test 6 and test 7 compares to test 8. The strlen() call was there only to make sure the value is actually accessed.
16-Jul-2005 06:42
To the last poster, regarding the speed tests:

<?php
$a
= str_repeat('text', 100);
$b = $a;
$c =& $a;
// $c == $b == $a

// But you assigned a different value within the functions:
$len = strlen($a); // $len != $a
?>

I was bemused; how could the processing times of the functions/no-functions tests be compared in this way? And calling the strlen() function within each iteration of the loop must take more time anyway?
www dot php dot net dot 2nd at mailfilter dot com dot ar
15-Jul-2005 08:39
I've been doing some performance tests. I thought I could squeeze some extra cyles using references, but I discovered they are more mysterious than I imagined (5.0.3).

Consider this:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) { $b = $a; unset($b); }

real    0m1.514s
user    0m1.433s
sys     0m0.071s

The above times (as others in this note) are the best out of three attempts in an idle Linux box.

I expected the above to be a bit slow, since constructing $b might imply copying the 40MB string each time. It was very fast, though. Let's try with references:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) { $b =& $a; unset($b); }

real    0m1.488s
user    0m1.380s
sys     0m0.071s

Not much of a gain, but it did took less time to complete. Will this work with functions? Let's see:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) dosome($a);
function dosome($arg){ $t = strlen($arg); }

real    0m3.518s
user    0m3.276s
sys     0m0.088s

Mmm... much slower, but still pretty nice. I didn't use references yet, so let's try them out:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 100 ; $n++ ) dosome($a);
function dosome(&$arg){ $t = strlen($arg); }

real    0m12.071s
user    0m6.190s
sys     0m5.821s

You think it is 3.5 times slower? Think again. It is 350,000 times slower. I had to limit the $n loop to 100 iterations in order to get those figures! I wonder what happens if I try to access the variable globally:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 1000000 ; $n++ ) dosome();
function dosome(){ $t = strlen($GLOBALS['a']); }

real    0m3.007s
user    0m2.918s
sys     0m0.074s

Notice that using $GLOBALS we're back in bussiness. So using the global keyword should be exactly the same, isn't it? Wrong again:

$a = str_repeat('hola',10000000);
for($n = 0 ; $n < 100 ; $n++ ) dosome();
function dosome(){ global $a; $t = strlen($a); }

real    0m12.423s
user    0m6.112s
sys     0m5.917s

We're in the '350,000 times slower' domain again. I wonder why the script is spending so much time in sys.

A couple of additional tests to complete the puzzle:

$a = str_repeat('hola',10000000); $b = Array(&$a);
for($n = 0 ; $n < 100 ; $n++ ) dosome();
function dosome(){ $t = strlen($GLOBALS['b'][0]); }

real    0m12.087s
user    0m6.068s
sys     0m5.955s

$a = str_repeat('hola',10000000); $b = Array(&$a);
for($n = 0 ; $n < 100 ; $n++ ) dosome();
function dosome(){ global $b; $t = strlen($b[0]); }

real    0m12.158s
user    0m6.023s
sys     0m5.971s

I guess the $GLOBALS trick doesn't help when we access a reference stored in the global variable.

I'm completely confused, now. At this light, I will review my usage of the global keyword as well as for the references. I hope someone can benefit from this study too.
jameslee at cs dot nmt dot edu
16-Jun-2005 03:33
It should be noted that a static variable inside a method is static across all instances of that class, i.e., all objects of that class share the same static variable.  For example the code:

<?php
class test {
    function
z() {
        static
$n = 0;
       
$n++;
        return
$n;
    }
}

$a =& new test();
$b =& new test();
print
$a->z();  // prints 1, as it should
print $b->z();  // prints 2 because $a and $b have the same $n
?>

somewhat unexpectedly prints:
1
2
kouber at php dot net
28-Apr-2005 06:36
If you need all your global variables available in a function, you can use this:

<?
function foo() {
 
extract($GLOBALS);
 
// here you have all global variables

}
?>
27-Apr-2005 05:46
Be careful if your static variable is an array and you return
one of it's elements: Other than a scalar variable, elements
of an array are returned as reference (regardless if you
didn't define them to be returned by reference).

<?php
function incr(&$int) {
  return
$int++;
}

function
return_copyof_scalar() {
  static
$v;
  if (!
$v)  
   
$v = 1;
  return(
$v);
}

function
return_copyof_arrayelement() {
  static
$v;
  if (!
$v) {
   
$v = array();
   
$v[0] = 1;
  }
  return(
$v[0]);
}

echo
"scalar: ".
    
incr(return_copyof_scalar()).
    
incr(return_copyof_scalar()).
    
"\n";
echo
"arrayelement: ".
    
incr(return_copyof_arrayelement()).
    
incr(return_copyof_arrayelement()).
    
"\n";
?>

Should print

scalar: 11
arrayelement: 11

but it prints:

scalar: 11
arrayelement: 12

as in the second case the arrays element was returned by
reference. According to a guy from the bug reports the
explanation for this behaviour should be somewhere here in
the documentation (in 'the part with title: "References with
global and static variables"'). Unfortunately I can't find
anything about that here. As the guys from the bug reports
are surely right in every case, maybe there is something
missing in the documentation. Sadly I don't have a good
explanation why this happens, so I decided to document at
least the behaviour.
vdephily at bluemetrix dot com
22-Apr-2005 03:51
Be carefull about nested functions :
<?php
// won't work :
function foo1()
{
 
$who = "world";
  function
bar1()
  {
    global
$who;
    echo
"Hello $who";
  }
}

// will work :
function foo2()
{
 
$GLOBALS['who'] = "world";
  function
bar2()
  {
    global
$who;
    echo
"Hello $who";
  }
}

// also note, of course :
function foo3()
{
 
$GLOBALS['who'] = "world";

 
// won't work
 
echo "Hello $who";

 
// will work
 
global $who;
  echo
"Hello $who";
}
?>
S dot Radovanovic at TriMM dot nl
15-Feb-2005 08:50
Sadly I have found out that I have been wrong about my statements below, why?

Well:
1. only the variables that were set in the constructor were 'live' in my referenced object
2. I was assigning this an object and not a reference

So:
I fixed nr. 1 by adding the & when initializing the object (this way this works on the initialized object and not a copy of it)
<?php
//screen factory
$objErrorConfig = & new Config("error.conf");
$objErrorConfig->setSection("messages");

//object factory
//If no file is stated, the last one is used, this way this instance will have the reference to the previously created instance of objErrorConfig in object screen
$objErrorConfig = & new Config();
$errorMessage = $objErrorConfig->get($errorName);
?>
Now the variables assigned after the constructor ($objErrorConfig->setSection("messages");) will also be 'live' in the static obj array.

I had to find a workaround for nr.2, since it is impossible to assign a reference to this. That's why I used code proposed by others, nl. I referenced all the members of the objects:
<?php
//Because we cannot make a direct reference from our object (by doing $this = & $theObject)
//we'll make references of our members
$arrClassVars = get_class_vars(get_class($theObject));
foreach(
$arrClassVars as $member=>$value) {
   
$this->$member = &$theObject->$member;
}               
//To make sure we are working with a reference we will store our new object as the reference
//in the singeltonobject array (so all other initialized (referenced) objects will have the
//newest one as super referer
$arrSingletonObject[$this->_configfile] = & $this;
?>

So in the end, I had better used what everbody was using (creating a Singleton through an method, instead of through the constructor), but hey, I learned something again :)
S dot Radovanovic at trimm dot nl
05-Feb-2005 03:54
To use the Singleton Pattern (as available in PHP5), we must do a little trick in PHP4.

Most examples I've seen look like this:
//Creation of singleton, Example, Example1 objects
//and then
<?
$myExample 
=& singleton('Example');
$myExample1 =& singleton('Example1');
?>

What I wanted was a way to use the Singleton Pattern on initialization of a new object (no calling of a method by reference (or something like that)).
The initializor doesn't have to know that the object it is trying to initialize uses the Singleton Pattern.
Therefor I came up with the following:

Beneath is part of a Config object that allows me to retrieve configuration data read from specific ini files (through parse_ini_file). Because I wanted to use the Config object in different other objects without having to pass a reference to the Config object all the time and without some of them having to now how the Config object was loaded (which configuration file was used) I had the need for the Singleton pattern.
To accomplish the Singleton pattern in the Constructor I've created a static array containing references to configuration file specific objects (each new configuration file creates a new instance of the Config object).
If we then try to create a new instance of an already loaded Config object (with the same configuration file), the objects set this to the reference of the previously created object, thus pointing both instances to the same object.
Here's the main part of the script.

Here's an example of how to use the Config object:
<?php
//dataheader
Config::setIniPath("/home/mydir/data/conffiles");

//object screen
$objTemplateConfig = new Config("template.conf");
$objErrorConfig = new Config("error.conf");

//objTemplateConfig and objErrorConfig are 2 different instances
$templatePath = $objTemplateConfig->get("template_path");
$errorColor = $objErrorConfig->get("error_color");

//object factory
//If no file is stated, the last one is used, this way this instance will have the reference to the previously created instance of objErrorConfig in object screen
$objErrorConfig = new Config();
$errorMessage = $objErrorConfig->get($errorName);
?>

So without the initializor knowing it he/she has retrieved a reference to a previously instantiated Config object (knowledge of this resides with the object).
Here's the constructor part of the config object:
S dot Radovanovic at trimm dot nl
05-Feb-2005 03:54
<?php
   
function __constructor($configfile = '', $blnSingleton = true) {   
       
//We must define a static array that contains our reference(s) to the object(s)
       
static $arrSingletonObject = array();
       
       
//We also need to specify a static local member, that keeps track of the last
        //initialize configfile, so that we can use this if no file has been specified
        //(this way we enable it for the initializor, to work with a previously initialized
        //config object, without knowing what configfile it uses
       
static $lastConfigfile;
               
        if(!empty(
$configfile)) {
           
//Store the set configfile name in the static local member
           
$lastConfigfile = $configfile;
           
        } else if(!empty(
$lastConfigfile)) {
           
           
//If the configfile was empty, we retrieve it from the last known initialized
           
$configfile = $lastConfigfile;
           
        } else {
           
//if we've reached so far, it means no configfile has been set at all (now
            //or previously), so we cannot continue
           
trigger_error("No configfile has been specified.", ERROR);
           
           
//Return (instead of an exit (or die)) so that the constructor isn't continued
           
return;
        }
       
       
//Set the configuration file
       
$this->_configfile = $configfile;
       
       
//Only if we want to use singleton we may proceed
       
if($blnSingleton) {
           
           
//We must now check to see if we already have a reference to the (to be created) config
            //object
           
if(!isset($arrSingletonObject[$this->_configfile])) {
               
//Create of reference of myself, so that it can be added to the singleton object array
               
$arrSingletonObject[$this->_configfile] = &$this;
               
               
//We can now proceed and read the contents of the specified ini file
               
$this->_parseIniFile();
               
            } else {
               
//Associate myself with the reference of the existing config object
               
$this = $arrSingletonObject[$this->_configfile];
            }
        }
    }
?>
pulstar at ig dot com dot br
08-Sep-2004 07:02
If you need all your global variables available in a function, you can use this:

<?php

function foo(parameters) {
  if(
version_compare(phpver