PHP变量的有效范围
参考资料:https://www.cnblogs.com/52php/p/5658177.html
参考资料:https://www.cnblogs.com/52php/p/5658178.html
一、包含文件
大部分的 PHP 变量只有一个单独的范围。这个单独的范围跨度同样包含了 include 和 require 引入的文件。
因为包含文件像它们是原始(包含)脚本的一部分那样工作,所以在 include() 那一行 之前定义 的变量 可供包含文件使用 。此外,包含 文件内定义的变量 可供 include() 那一行 之后的父(包含)脚本使用。
<?php
$a = 1;
include "b.inc";
?>
这里变量 $a 将会在包含文件 b.inc 中生效。
二、常量
常量一旦被声明将可以在全局可见,也就是说,它们可以函数内外使用,但是这仅仅限于一个页面之中(包含我们通过include和include_once)包含进来的PHP脚本,但是在其他的页面中就不能使用了。
三、函数中的变量
在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内。
<?php
$a = 1; /* global scope */
function Test() {
echo $a; /* reference to local scope variable */
}
Test();
?>
此时,并不会输出 1。因为,在缺省的情况下,函数内部是无法使用外部的变量的。如果要使用外部的变量,需要先使用global在内部声明,声明的变量名需要与外部的变量名一致。或者使用超全局变量$GLOBALS[‘key’],其中的键值为外部的变量名。
四、global与$GLOBAL
global与$GLOBAL都能够使函数内部使用外部的变量。
例子 : 使用 global
<?php
$a = 1;
$b = 2;
function Sum() {
global $a, $b;
$b = $a + $b;
}
Sum();
echo $b;
?>
此时,将会输出 3。
例子 : 使用 $GLOBALS
<?php
$a = 1;
$b = 2;
function Sum() {
$GLOBALS["b"] = $GLOBALS["a"] + $GLOBALS["b"];
}
Sum();
echo $b;
?>
同样地,也会输出 3。
在$ GLOBALS数组中,每一个变量为一个元素,键名对应变量名,值变量的内容。$ GLOBALS之所以在全局范围内存在,是因为
$ GLOBALS 是一个超全局变量。
但是,global与$ GLOBALS还是有所不同的,请看下面例子:
<?PHP
function test_global() {
global $var1, $var2;
$var2 =& $var1;
}
function test_globals() {
$GLOBALS['var3'] =& $GLOBALS['var1'];
}
$var1 = 5;
$var2 = $var3 = 0;
test_global();
print $var2 ."n";
test_globals();
print $var3 ."n"; ?>
输出结果为:0和5。
这是应为:global在函数产生 一个指向函数外部变量的别名变量,而不是真正的函数外部变量。而$ GLOBALS这是一个“superglobal”,或者可以描绘为主动全局变量,即上述代码中的
$ var1和$ GLOBALS[‘var1’]是指的同一变量,而不是2个不同的变量!
test_global中的“$ var2 =& $ var1;”,上面是一个引用赋值运算,也就是:原来$ var2指向的是全局变量$ var2的物理内存地址。在此语句执行后,$ var2将指向$ var1所指向的物理内存地址。
五、超全局变量
超级全局变量(共9个)的完整列表如下:
超全局变量,在函数内部,直接就可以使用。
- $ GOBALS: 所有全局变量数组
- $ _SERVER: 服务器环境变量数组
- $ _POST: 通过POST方法传递给该脚本的变量数组
- $ _GET: 通过GET方法传递给该脚本的变量数组
- $ _COOKIE: cookie变量数组
- $ _FILES: 与文件上传相关的变量数组
- $ _ENV: 环境变量数组
- $ _REQUEST: 所有用户输入的变量数组包括 $ _GET、 $ _POST 、$ _COOKIE 所包含的输入内容
- $_SESSION: 会话变
例子:
<?php
function test_global() {
// 大多数的预定义变量并不 "super",它们需要用 'global' 关键字来使它们在函数的本地区域中有效。
global $HTTP_POST_VARS;
print $HTTP_POST_VARS['name'];
// Super globals 在任何范围内都有效,它们并不需要 'global' 声明。Super globals 是在 PHP 4.1.0 引入的。
print $_POST['name'];
}
?>
此时就会直接输出$ POST中键值为 name 的值。
六、静态变量
变量范围的另一个重要特性是静态变量(static variable)。静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。 在程序全部结束后,才会清除。
例子:
<?php
function Test() {
static $a = 0;
echo $a;
$a++;
}
?>
使用关键字 static进行声明。
注意点:
<?php
function foo() {
static $int = 0; // correct
static $int = 1+2; // wrong (as it is an expression)
static $int = sqrt(121); // wrong (as it is an expression too)
$int++;
echo $int;
}
?>
如果在声明中用 “表达式的结果” 对其赋值会导致 解析错误 。
七、全局和静态变量的引用
在 Zend 引擎 1 代,驱动了 PHP4,对于变量的 static 和 global 定义是以 references 的方式实现的。例如,在一个函数域内部用 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 "<br/>";
$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() 函数时其值并没有被记住。