|
|
 |
The scope of a variable is the context within which it is defined. For the most part all PHP variables only have a single scope. This single scope spans included and required files as well. For example:
變數的範圍只是在其所定義的空間內存在(也就是它的生效范围)。在大部份的情況下,PHP 的變數只有一個單一的範圍。這單一的範圍也包含了以 include 和 require 方式引入的檔案。例如:
Here the $a variable will be available within the included b.inc script. However, within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope. For example:
这里变量 $a 将会在包含文件 b.inc 中生效。但是,在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内。例如:
PHP 的全局变量和 C 语言有一点点不同,在 C 语言中,全局变量在函数中自动生效
This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope.
You may notice that this is a little bit different from the C language in that global variables in C are automatically available to functions unless specifically overridden by a local definition. This can cause some problems in that people may inadvertently change a global variable.
In PHP global variables must be declared global inside a function if they are going to be used in that function.
這個程式不會輸出任何東西,因為 echo 述句使用了本區域版本的 $a
變數,而該本區域變數並未曾被分配一個值。
你會發現這和 C 語言的做法不同,因為 C
的全域變數是自動的提供給各函數,除非在本域定義中指明撤銷(被局部变量覆盖)。此做法可能會引致一些問題,如使用者不慎地更改了全域變數的值。
在 PHP
中,全域變數在函數 使用前必須先宣佈為全域global。例子:
global 关键字
The above script will output "3". By declaring $a and $b global within the function, all references to either variable will refer to the global version. There is no limit to the number of global variables that can be manipulated by a function.
上述例子將會輸出 "3"。在函數內宣佈 $a 及 $b 為全域後,所有涉及該兩個變數的使用將自動指向全域的版本(任何变量的所有引用变量都会指向到全局变量)。PHP 沒有限定一個函數可以使用的全域變數的數量。
A second way to access variables from the global scope is to use the special PHP-defined $GLOBALS array. The previous example can be rewritten as:
第二種存取全域範圍中的變數方法是使用一個由 PHP 特別定義的陣列:$GLOBALS。前面的例子可以重寫為:
The $GLOBALS array is an associative array with the name of the global variable being the key and the contents of that variable being the value of the array element.
Notice how $GLOBALS exists in any scope, this is because $GLOBALS is a superglobal. Here's an example demonstrating the power of superglobals:
$GLOBALS 是一個關聯陣列 (associative array),全域變數的名即為索引鍵,而該變數的內容即為陣列的值。(每一个变量为一个元素,键名对应变量名,值对应变量的内容)
留意 $GLOBALS 在任何一個範圍都出現?那是因為 $GLOBALS 是一個superglobal。這是一個示範 superglobals 強大功能的例子:
使用静态变量 static variable
Another important feature of variable scoping is the static variable. A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope. Consider the following example:
變數範圍的另一個重要功能為靜態變數。靜態變數只在本域函數範圍內存在,但是當程式執行離開此範圍時,它並不會喪失它的值。看看下面的例子:
This function is quite useless since every time it is called it sets $a to 0 and prints "0". The $a++ which increments the variable serves no purpose since as soon as the function exits the $a variable disappears.
To make a useful counting function which will not lose track of the current count, the $a variable is declared static:
此函數沒有什麼用處,因每一次執行它時,它將 $a 設為 0 然後列印出 "0"。$a++ 增加了 $a 的值,但並沒有實際用途因為一旦離開了該函數,變數 $a 也隨之消失。
要設計一個有用的、不會丟失當前計數的計數函數,我們可以將 $a宣佈為靜態:
Now, every time the Test() function is called it will print the value of $a and increment it.
Static variables also provide one way to deal with recursive functions.
A recursive function is one which calls itself. Care must be taken when writing a recursive function because it is possible to make it recurse indefinitely. You must make sure you have an adequate way of terminating the recursion. The following simple function recursively counts to 10, using the static variable $count to know when to stop:
現在,每當函數 Test() 被呼叫時,它會列印出 $a 的值,然後加上一。
靜態變數也提供一種處理遞迴函數(递归函数)的方法。
遞迴函數 recursive functions是一種呼叫自己的函數。編寫遞迴函數時必須留意,因為若編寫錯誤,它有可能會無定限地遞迴。您必須確定足夠的方式來終止遞迴。下列簡單的函數將遞迴地數到 10,利用靜態變數 $count 來斷定什麼時候停止:
驅動 PHP 4 的 Zend Engine 1 是以參照的方式來實現 static 和 global 的。例如,一個真正的全域變數使用 global 方式引進一個函數範圍時實際上就是建立了一個全域變數的參照。這將導致一些意想不到的行為,正如下列例子所述:
執行這個例子將會導致下列的輸出: NULL
object(stdClass)(0) {
} |
static 述式也會導致同樣的輸出。參照並沒有被靜態地儲存:
執行此例子將導致下列的輸出:
Static object: NULL
Static object: NULL
Static object: NULL
Static object: object(stdClass)(1) {
["property"]=>
int(1)
} |
上述例子示範了在指派一個參照給予一個靜態變數後,當您第二次呼叫 &get_instance_ref() 函數時,它是不會記住之前的值的。
26-May-2006 10:56
When I first was writing my last comment, I was thinking that somehow
there was a php bug causing two separate global namespaces.
As I was composing the post I realized that perhaps the problem was
unsetting the variable, and removed all my references to two namespaces.
Now in reviewing some of the posts below which discuss the issue of
unsetting global variables as an issue, I think that the unsetting is
the problem, and that the preferred method is not to unset them but
assign null to them.
jas at rephunter dot net
26-May-2006 10:36
I have run into a situtation using PHP 5.0.4 that has shown the using
the global statement is not exactly equvalent to the use of the
$GLOBALS superglobal.
My code unsets and initializes a specific variable in some lower level
functions, with the intent that it be a global variable, using the
global statement. That is, in every function in which the variable
appears, it is declared as global.
Specifically, when tracing the program, I can see a global instance and
a local instance with different values. This was causing a bug in my
program.
Of course this makes no sense.
I think it that unsetting the variable in the lower level function
could be the problem. Perhaps when the "global" version is unset, then
initialed again, it is no longer global.
So, either there is a bug in 5.0.4, or there is something that I am not doing correctly.
In any case, the workaround is to replace each occurrence of the
variable_name with $GLOBALS['variable_name'] and removing it from all
global statements.
Although I would have thought that using the superglobal should be
equivalent to using the global statement as it seems to be documented,
it is not, and now there is now only a single instance of the variable
as intended, and the bug is fixed.
jason
29-Apr-2006 06: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
04-Apr-2006 04:37
You could get around that:
<?php
function someFunction () {
static $isInitialized = 0;
static $otherStatic = 0; if (!$isInitialized) {
$otherStatic = function(); $isInitialized = 1;
}
...
}
?>
Needs an extra variable and evaluates a condition every time it's run, but it does get around your problem.
SasQ
01-Apr-2006 05: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
23-Mar-2006 07: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
11-Feb-2006 08: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
31-Dec-2005 01: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; echo $b->var; ?>
warhog at warhog dot net
13-Dec-2005 04: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";
$a->func_having_static_var(3);
echo $a->func_having_static_var()."\n";
echo $b->func_having_static_var()."\n";
?>
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
01-Nov-2005 12: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; $a =& $GLOBALS['a']; ?>
If you've read http://php.net/references , then everything behaves as you'd expect.
tc underline at gmx TLD ch
14-Sep-2005 06: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 11: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 09: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.
17-Jul-2005 08:42
To the last poster, regarding the speed tests:
<?php
$a = str_repeat('text', 100);
$b = $a;
$c =& $a;
$len = strlen($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
16-Jul-2005 10: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
17-Jun-2005 05: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(); print $b->z(); ?>
somewhat unexpectedly prints:
1
2
kouber at php dot net
28-Apr-2005 08: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 07: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 05:51
Be carefull about nested functions :
<?php
function foo1()
{
$who = "world";
function bar1()
{
global $who;
echo "Hello $who";
}
}
function foo2()
{
$GLOBALS['who'] = "world";
function bar2()
{
global $who;
echo "Hello $who";
}
}
function foo3()
{
$GLOBALS['who'] = "world";
echo "Hello $who";
global $who;
echo "Hello $who";
}
?>
S dot Radovanovic at TriMM dot nl
15-Feb-2005 11: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
$objErrorConfig = & new Config("error.conf");
$objErrorConfig->setSection("messages");
$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
$arrClassVars = get_class_vars(get_class($theObject));
foreach($arrClassVars as $member=>$value) {
$this->$member = &$theObject->$member;
}
$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 06: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
Config::setIniPath("/home/mydir/data/conffiles");
$objTemplateConfig = new Config("template.conf");
$objErrorConfig = new Config("error.conf");
$templatePath = $objTemplateConfig->get("template_path");
$errorColor = $objErrorConfig->get("error_color");
$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 06:54
<?php
function __constructor($configfile = '', $blnSingleton = true) {
static $arrSingletonObject = array();
static $lastConfigfile;
if(!empty($configfile)) {
$lastConfigfile = $configfile;
} else if(!empty($lastConfigfile)) {
$configfile = $lastConfigfile;
} else {
trigger_error("No configfile has been specified.", ERROR);
return;
}
$this->_configfile = $configfile;
if($blnSingleton) {
if(!isset($arrSingletonObject[$this->_configfile])) {
$arrSingletonObject[$this->_configfile] = &$this;
$this->_parseIniFile();
} else {
$this = $arrSingletonObject[$this->_configfile];
}
}
}
?>
pulstar at ig dot com dot br
09-Sep-2004 09:02
If you need all your global variables available in a function, you can use this:
<?php
function foo(parameters) {
if(version_compare(phpversion(),"4.3.0")>=0) {
foreach($GLOBALS as $arraykey=>$arrayvalue) {
global $$arraykey;
}
}
}
?>
info AT SyPlex DOT net
01-Sep-2004 08:35
Some times you need to access the same static in more than one function. There is an easy way to solve this problem:
<?php
function &getStatic() {
static $staticVar;
return $staticVar;
}
function fooCount() {
$ref2static = & getStatic();
echo $ref2static++;
}
fooCount(); fooCount(); fooCount(); ?>
shyam dot g at gmail dot com
03-Jul-2004 06:52
in response to Michael's comments, it is imperative to observe that
static variables in methods of an object are not class level variables.
and since both a and b from the previous example are 2 different
objects, there is no question of the static variable being shared
between the objects.
The variable is static with respect to the function and not the class.
sam
Michael Bailey (jinxidoru at byu dot net)
05-Jun-2004 02:43
Static variables do not hold through inheritance. Let class A
have a function Z with a static variable. Let class B extend
class A in which function Z is not overwritten. Two static
variables will be created, one for class A and one for class B.
Look at this example:
<?php
class A {
function Z() {
static $count = 0;
printf("%s: %d\n", get_class($this), ++$count);
}
}
class B extends A {}
$a = new A();
$b = new B();
$a->Z();
$a->Z();
$b->Z();
$a->Z();
?>
This code returns:
A: 1
A: 2
B: 1
A: 3
As you can see, class A and B are using different static variables even though the same function was being used.
Randolpho
03-Apr-2004 04:53
More on static variables:
My first not is probably intuitive to most, but I didn't notice it
mentioned explicitly, so I'll mention it: a static variable does not
retain it's value after the script's execution. Don't count on it being
available from one page request to the next; you'll have to use a
database for that.
Second, here's a good pattern to use for declaring a static variable based on some complex logic:
<?
function buildStaticVariable()
{
$foo = null;
// some complex expression or set of
// expressions/statements to build
// the return variable.
return $foo;
}
function functionWhichUsesStaticVar()
{
static $foo = null;
if($foo === null) $foo = buildStaticVariable();
// the rest of your code goes here.
}
?>
Using such a pattern allows you to separate the code that creates your
default static variable value from the function that uses it. Easier to
maintain code is good. :)
jmarbas at hotmail dot com
17-Jan-2004 07:34
Whats good for the goose is not always good for the iterative gander.
If you declare and initialize the static variable more than once inside
a function ie.
function Test(){
static $count = 0;
static $count = 1;
static $count = 2;
echo $count;
}
the variable will take the value of the last declaration. In this case $count=2.
But! however when you make that function recursive ie.
function Test(){
static $count = 0;
static $count = 1;
static $count = 2;
$count++;
echo $count;
if ($count<10){
Test();
}
}
Every call to the function Test() is a differenct SCOPE and
therefore the static declarations and initializations are NOT executed
again. So what Im trying to say is that its OK to declare and
initialize a static variable multiple times if you are in one
function... but its NOT OK to declare and initialize a static variable
multiple times if you call that same function multiple times. In other
words the static variable is set once you LEAVE a function (even if you
go back into that very same function).
Jack at soinsincere dot com
15-Nov-2003 02:11
Alright, so you can't set a static variable with a reference.
However, you can set a static variable to an array with an element that is a reference:
<?php
class myReference {
function getOrSet($array = null) {
static $myValue;
if (!$array) {
return $myValue[0]; }
$myValue = $array; static $myValue;
}
}
$static = "Dummy";
$dummy = new myReference;
$dummy->getOrSet(array(&$static));
$static = "Test";
print $dummy->getOrSet();
?>
flobee at gmx dot net
06-Nov-2003 04:26
i found out that on any (still not found) reason the <?php static $val =NULL; ?> is not working when trying to extract the data form the $var with a while statment
e.g.:
<?php
funktion get_data() {
static $myarray = null;
if($myarray == NULL) {
$myarray = array('one','two');
}
while(list($key,$val) = each( $myarray ) ) {
echo "x: $key , y: $val";
}
}
?>
when using foreach($myarray AS $key => $val) { .... instad of while then i see the result!
ppo at beeznest dot net
09-Jul-2003 09:59
Even if an included file return a value using return(), it's still sharing the same scope as the caller script!
<?php
$foo = 'aaa';
$bar = include('include.php');
echo($foo.' / '.$bar);
?>
where include.php is
<?php
$foo = 'bbb';
return $foo;
?>
The output is: bbb / bbb
Not: aaa / bbb
j at superjonas dot de
15-Mar-2003 02:08
> pim wrote:
> in addition:
> if you define a function in that included file, it can't get
> the variables from the inluded file's scope. global won't work.
> The only way to give such an include function access to global
> vars is via arguments. I don't know if this is a bug in PHP.
>
> //---- from within function included file -----
> echo $var1; // this one works
> function foo()
> {
> global $var1;
> echo $var1; // this one doesn't
> }
It works if you additionally declare the variables from the inluded file's scope as global.
example:
<?php
function func1() {
include("file2.php");
func2();
}
func1();
?>
<?php
global $var; $var = 'something';
function func2() {
global $var; echo $var; }
?>
ben-xo aatt dubplates.org
13-Mar-2003 02:05
regarding the above "unset" example: I quote from the manual page for "unset".
"If a static variable is unset() inside of a function, unset() destroyes the variable and all its references. "
As mentioned above, on this page, static vars are implemented as
references. When you unset() a reference, what you are doing is
deleting a particular name for that variable. In your example, you
delete the LOCAL NAME $a, but the static contents are still there
(hidden) and next time you call your function, a NEW LOCAL NAME (again
$a...) is linked to the SAME backing data.
Workaround would be something like "$a = null".
unset($a) is very much like $a = &null however, which, if you read
the notes above, won't have the desired affect on static or global
variables.
04-Mar-2003 11:25
As far as I can see, it's not possible to unset() a static variable inside the function:
function Test($unset = false) {
static $a = 0;
echo $a++;
if ($unset) unset($a);
}
Test();
Test();
Test(true);
Test();
Test();
This will output 01234. I would expect it to at least show 01201.
pim at lingewoud dot nl
28-Feb-2003 03:46
shevek wrote:
>> If you include a file from within a function using include(),
>> the included file inherits the function scope as its own
>> global scope, it will not be able to see top level globals
>> unless they are explicit in the function.
in addition:
if you define a function in that included file, it can't get the
variables from the inluded file's scope. global won't work. The only
way to give such an include function access to global vars is via
arguments. I don't know if this is a bug in PHP.
//---- from within function included file -----
echo $var1; // this one works
function foo()
{
global $var1;
echo $var1; // this one doesn't
}
jg at nerd-boy dot net
08-Feb-2003 08:10
It's possible to use a variable variable when specifying a variable as
global in a function. That way your function can decide what global
variable to access in run-time.
function func($varname)
{
global $$varname;
echo $$varname;
}
$hello = "hello world!";
func("hello");
This will print "hello world!", and is roughly the same as passing by
reference, in the case when the variable you want to pass is global.
The advantage over references is that they can't have default
parameters. With the method above, you can do the following.
function func($varname = FALSE)
{
if ($varname === FALSE)
echo "No variable.";
else
{
global $$varname;
echo $$varname;
}
}
$hello = "hello world!";
func("hello"); // prints "hello world!"
func(); // prints "No variable."
wjs@sympaticoDOTca
11-Dec-2002 01:03
Becareful where you define your global variables:
This will work:
<?php
$MyArray = array("Dog");
function SeeArray(){
global $MyArray;
if (in_array("Dog",$MyArray)){
foreach ($MyArray as $Element){
echo "$Element <hr/>";
}
}
}
SeeArray();
?>
while this will not:
<?php
SeeArray();
$MyArray = array("Dog");
function SeeArray(){
global $MyArray;
if (in_array("Dog",$MyArray)){ foreach ($MyArray as $Element){
echo "$Element <hr/>";
}
}
}
?>
jez at india dot com
01-Nov-2002 04:35
If anyone needs a permanent array / hash, similar in functionality to ASP's application object, check out the article on
http://zez.org/article/articleview/46/1/
which has some working code (written by me) attached. This code
implements a hash with application scope, i.e. its contents can be
accessed from all php scripts running on the same computer. You could
use it, for example, to globally cache configuration settings for a
site.
The hash is also cached in the db, i.e. it's inviolable. Its contents
are buffered in memory, so there's no hit on the db when accessing the
hash apart from the first time you read it, and of course when you
write to it.
mu at despammed dot com
16-Oct-2002 07:12
morthanpurpl: You don't have to initialize variables you use first
inside a variable, at least not in PHP4.2.2. The following will just
work fine and output "iam":
<?php
function dumdum()
{
global $a;
$a = "iam";
}
dumdum();
echo $a;
?>
heatwave at fw dot hu
15-Oct-2002 08:12
Some people (including me) had a problem with defining a long GLOBAL
variable list in functions (very error prone). Here is a possible
solution. My program parses php file for functions, and compiles GLOBAL
variable lists. Then you can just remove from the list those variables
which need not be global.
<?php
$pfile=file("myfile.php4");
for($i=0;$i<sizeof($pfile);$i++) {
if(eregi("function",$pfile[$i])) {
list($part1,$part2)=sscanf($pfile[$i],"%s %s");
echo "\n\n $part1 $part2:\nGLOBAL ";
$varlist=array();
$level=0; $end=$i;
do {
$lpar=explode("{",$pfile[$end]);
$level+=sizeof($lpar)-1;
$lpar=explode("}",$pfile[$end]);
$level-=sizeof($lpar)-1;
$end++;
} while(($end<sizeof($pfile))&&($level>0));
$pstr="";
for($j=$i;$j<=$end;$j++) $pstr.=$pfile[$j];
$lpar=explode("$",$pstr);
for($j=1;$j<sizeof($lpar);$j++) {
eregi('[a-zA-Z_][a-zA-Z0-9_]*',$lpar[$j],$cvar);
$varlist[$cvar[0]]=1;
}
array_walk($varlist,'var_print');
}
}
function var_print ($item, $key) {
echo "$key,";
}
?>
stlawson AT sbcglobal DOT net
06-Jul-2002 11:22
aslak is right! Check this out:
$t1 = "outie";
function foo1()
{
global $t1;
$t1 = 'innie' ;
echo ('in foo1() $t1 is an ' . $t1) ;
}
echo ('before foo1() $t1 is an ' . $t1) ;
foo1() ;
echo ('after foo1() $t1 is an ' . $t1) ;
// is identical to?:
$t2 = "outie";
function foo2()
{
$t2 = &$GLOBALS['t2'];
$t2 = 'innie' ;
echo ('in foo2() $t2 is an ' . $t2) ;
}
echo ('before foo2() $t2 is an ' . $t2) ;
foo2() ;
echo ('after foo2() $t2 is an ' . $t2) ;
Output:
before foo1() $t1 is an outie
in foo1() $t1 is an innie
after foo1() $t1 is an innie
before foo2() $t2 is an outie
in foo2() $t2 is an innie
after foo2() $t2 is an innie
Also I cleaned up aslak's code a bit ;)
aslak at novita dot no
27-Jun-2002 07:54
Basicly what happens is this:
$var t;
function foo()
{
global $t;
}
is identical to:
function foo()
{
$t=&$GLOBALS[t];
}
which will answer the above argument becouse when you use
$t=&$somelocal;
you overwrite the first $t=&.....
cellog at users dot sourceforge dot net
03-Jun-2002 08:57
regarding May 27 comment.
Try this file, and you will see that what I said in my comment holds:
<?php
$testvar = 1 ;
$testvar2 = 2 ;
function foo ()
{
global $testvar ;
global $testvar2 ;
$testvar3 = 6;
$testvar = 3 ; echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3 <br>" ; $testvar = 4 ; echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3 <br>" ; $testvar = &$testvar2 ; echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br> " ; $testvar=5 ; echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br>" ; $testvar = &$testvar3;
echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br>" ; $testvar = 7; echo "$testvar,$GLOBALS[testvar],$GLOBALS[testvar2],$testvar3<br>" ; }
foo() ;
?>
doing $testvar = &$testvar2 assigns $testvar to point at $testvar2,
which is pointing at $GLOBALS[testvar2]. Later, I assign $testvar
= &$testvar3, which points it at the local variable.
The & operator *only* changes what the left-hand variable points
at, and not the contents of what it used to point at (to borrow from
old-fashioned pointer terminology :).
JeanRobert at Videotron dot ca
28-May-2002 05:18
Comment on May 21.
This explanation does not explain why assigning a global variable
reference to a globalvariable does not modify it (See the statement
"$testvar = &$testvar2" bellow).
Here is my own explanation:
Inside a function, if we assign a variable reference to a global
variable then this global variable is replaced by a new local
variable instance. In other words, once done, futur assignment to
this variable will only modify the local copy and leave the original
global variable unchanged. Looking at the following code will
help you to understand it. (Just as a reminder $GLOBALS[testvar]
always refers to the original $testvar global variable).
$testvar = 1 ;
$testvar2 = 2 ;
function foo ()
{
global $testvar ;
global $testvar2 ;
$testvar = 3 ; //Assigning a constant works as expected.
echo "$testvar,$GLOBALS[testvar] " ; // 3,3
$testvar = 4 ; //Assigning a variable also works as expected.
echo "$testvar,$GLOBALS[testvar] " ; // 4,4
$testvar = &$testvar2 ; // Assiging a reference allocates a new
// local testvar instance.
echo "$testvar,$GLOBALS[testvar] " ; // 2,4
$testvar=5 ; // Assigning a value to testvar now only modifies
// the local instance.
echo "$testvar,$GLOBALS[testvar]" ; //5,4
}
foo() ;
If you plan to assign a variable reference to a global variale then
you should use '$GLOBALS[testvar]=&$variable' instead of
'$testvar=&$variable'.
cellog at users dot sourceforge dot net
22-May-2002 07:02
comment on april 9 regarding:
function foo ()
{
global $testvar;
$localvar = new Object ();
$testvar = &$localvar;
}
The reason this doesn't work is that when you use & to assign to
$testvar, it reassigns $testvar to point at what $localvar points at.
$testvar = $localvar should work as well as $GLOBALS['testvar'] =
&$localvar, although instance data will be copied and any
references to parent classes will be broken. I hate that :).
In other words, the declaration "global $testvar;" is telling php "make
$testvar point at the same location as $GLOBALS['testvar']" but
"$testvar = &$localvar" tells php "make $testvar point at the same
location as $localvar"!!!
01-May-2002 04:14
Seems as though when a cookie is saved and referenced as a variable of
the same name as the cookie, that variable is NOT global. If you
make a function ro read the value of the cookie, the cooke variable
name must be declared as a global.
example:
function ReturnCookie()
{
$cookieName = "Test_Cookie";
global $$cookieName;
if (isset($$cookieName))
{
echo ("$cookieName is set");
$returnvalue = $$cookieName;
}
else
{
$newCookieValue = "Test Value";
setcookie("$cookieName","$newCookieValue", (time() + 3153600));
echo ("made a cookie:" . $newCookieValue ."<BR>");
$returnvalue = $newCookieValue;
}
echo ("the cookie that was set is now $returnvalue <BR>");
return $returnvalue;
}
huntsbox at pacbell dot net
03-Apr-2002 12:11
Not sure of the implications of this but...
You can create nested functions within functions but you must make sure they aren't defined twice, e.g.:
function norm($a, $b) {
static $first_time = true;
if ($first_time) {
function square($x) {
return $x * $x;
}
$first_time = false;
}
return sqrt(square($a) + square($b));
}
print square(5); // error, not defined yet
print norm(5,4);
print "<br>";
print norm(3,2);
print square(5); // OK
If you don't include the if ($first_time) you get an error saying you
can't define square() twice. Note that square is not local to the
function it just appears there. The last line successfully
accesses square in the page scope. This is not terribly useful,
but interesting.
jochen_burkhard at web dot de
30-Mar-2002 03:47
Please don't forget:
values of included (or required) file variables are NOT available in
the local script if the included file resides on a remote server:
remotefile.php:
<?PHP
$paramVal=10;
?>
localfile.php:
<?PHP
include "http://otherserver.com/remotefile.php";
echo "remote-value= $paramVal";
?>
Will not work (!!)
steph_rondinaud at club-internet dot fr
09-Feb-2002 08:41
I'm using PHP 4.1.1
While designing a database access class, I needed a static variable
that will be incremented for all instances of the class each time the
class connected to the database. The obvious solution was to declare a
"connection" class variable with static scope. Unfortunatly, php
doesn't allow such a declaration.
So I went back to defining a static variable in the connect method of
my class. But it seems that the static scope is not inherited: if class
"a" inherit the "db access" class, then the "connection" variable is
shared among "a" instances, not among both "a" AND "db access"
instances.
Solution is to declare the static variable out of the db access class, and declare "global" said variable in the connect method.
admin at essentialhost dot com
04-Feb-2002 10:30
Quick tip for beginners just to speed things up:<P>
If you have a bunch of global variables to import into a function, it's
best to put them into a named array like $variables[stuff].
<P>
When it's time to import them you just so the following; <P>
function here() {
$vars = $GLOBALS['variables'];
print $vars[stuff];
}
This really helps with big ugly form submissions.
tomek at pluton dot pl
11-Dec-2001 02:53
When defining static variables you may use such declarations:
static $var = 1; //numbers
static $var = 'strings';
static $var = array(1,'a',3); //array construct
but these ones would produce errors:
static $var = some_function('arg');
static $var = (some_function('arg'));
static $var = 2+3; //any expression
static $var = new object;
danno at wpi dot edu
24-Jul-2001 03:28
WARNING! If you
create a local variable in a function and then within that function
assign it to a global variable by reference the object will be
destroyed when the function exits and the global var will contain
NOTHING! This main sound obvious but it can be quite tricky you
have a large script (like a phpgtk-based gui app ;-) ).
example:
function foo ()
{
global $testvar;
$localvar = new Object ();
$testvar = &$localvar;
}
foo ();
print_r ($testvar); // produces NOTHING!!!!
hope this helps someone before they lose all their hair
carpathia_uk at mail dot com
08-May-2001 05:21
On confusing aspect about global scope...
If you want to access a variable such as a cookie inside a
function, but theres a chance it may not even be defined, you need to
access it using he GLOBALS array, not by defining it as global.
This wont work correctly....
function isLoggedin()
{
global $cookie_username;
if (isset($cookie_username)
echo "blah..";
}
This will..
function isLoggedin()
{
if (isset($GLOBALS["cookie_username"]))
echo "blah..";
}
shevek at anarres dot org
05-Feb-2000 08:51
If you include a file
from within a function using include(), the included file inherits the
function scope as its own global scope, it will not be able to see top
level globals unless they are explicit in the function.
$foo = "bar";
function baz() {
global $foo; # NOTE THIS
include("qux");
}
| |