php中global和$GLOBALS[]的分析之一


Posted in PHP onFebruary 02, 2012

这可能引起一些问题,有些人可能漫不经心的改变一个全局变量。PHP 中全局变量在函数中使用时必须申明为全局(注意,Global这个关键字在函数中定义才有用)。
1:Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件。

<?PHP 
$a=123; 
function aa() 
{ 
Global $a; //如果不把$a定义为global变量,函数体内是不能访问函数体外部的$a的,但是可以定义一个相同的名字$a,此时这个变量是局部变量,等同于C语言的局部变量,只能在函数体内部使用。 
echo $a; 
} 
aa(); 
?>

总结:在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用,
$global $a; 
$a=123; 
function f() 
{ 
echo $a; //错误, 
} 
//再看看下面一例 
function f() 
{ 
global $a; 
$a=123; 
} 
f(); 
echo $a; //正确,可以使用

2:global问题解析:
question:我在 config.inc.php中定义了一些变量($a),在别的文件中函数外部 include("config.inc.php"),函数内部需要使用这些变量$a,如果没有声明的话,echo $a是打印不出来任何东西的。因此声明global $a,但是有很多函数和很多变量,总不能不断重复的这样声明吧?有什么好的解决办法,请指点。
answer1:先在config.inc.php里定义常量:define(常量名,常量值)
再在其他需要用到的地方require 'config.inc.php',
然后就能在这个文件里直接使用这个常量了。
answer2:我也有个办法,就是定义数组,如$x[a],$x,那样就只要声明global $x一个了。
answer3:我试了你的这个方法,不行啊。
answer4:改你的php.ini文件。
3.一些Global和$GLOBALS 数组的例子

例子:使用 global

<?PHP 
$w3sky = 1; 
$w3sky2 = 2; 
function Sum() 
{ 
global $w3sky, $w3sky2;$w3sky2 = $w3sky + $w3sky2; 
}Sum(); 
echo $w3sky2; 
?>

以上脚本的输出将是“3”。在函数中申明了全局变量 $w3sky 和 $w3sky2,任何变量的所有引用变量都会指向到全局变量。对于一个函数能够申明的全局变量的最大个数,PHP 没有限制。
在全局范围内访问变量的第二个办法,是用特殊的 PHP 自定义 $GLOBALS 数组。前面的例子可以写成:
例子 使用 $GLOBALS 替代 global
<?PHP 
$w3sky = 1; 
$w3sky2 = 2;function Sum() 
{ 
$GLOBALS['w3sky'] = $GLOBALS['w3sky'] + $GLOBALS['w3sky2']; 
}Sum(); 
echo $w3sky2; 
?>

在 $GLOBALS 数组中,每一个变量为一个元素,键名对应变量名,值对应变量的内容。$GLOBALS 之所以在全局范围内存在,是因为 $GLOBALS 是一个超全局变量。以下范例显示了超全局变量的用处:
例子 演示超全局变量和作用域的例子
<?PHP 
function test_global() 
{ 
// 大多数的预定义变量并不 "super",它们需要用 'global' 关键字来使它们在函数的本地区域中有效。 
global $HTTP_POST_VARS;echo $HTTP_POST_VARS['name'];// Superglobals 在任何范围内都有效,它们并不需要 'global' 声明。Superglobals 是在 PHP 4.1.0 引入的。 
echo $_POST['name']; 
} 
?>

global 也就是说在一个文件里 只要你声明为global $db 那么在声明的下面 你就可以引用这个$db了。
4.原来以为global和$GLOBALS除了写法不一样以为,其他都一样,可是在实际应用中发现,2者的区别还是很大的!
先看下面的例子:
<?php 
// 例子1 
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
怎么会这样呢?不应该是2个5吗?怎么会出现1个0和1个5呢?
恩,我们保留以上问题,深入分析$GLOBALS和global的原理!
我们都知道变量其实是相应物理内存在代码中的"代号",假设我们上面声明的3个变量分配的内存如下图表示:
引用php手册的$GLOBALS的解释:
Global 变量:$GLOBALS
注意: $GLOBALS 在 PHP 3.0.0 及以后版本中适用。
由所有已定义全局变量组成的数组。变量名就是该数组的索引。
这是一个“superglobal”,或者可以描述为自动全局变量。
也就是说上面代码中的$var1和$GLOBALS['var1']是指的同一变量,而不是2个不同的变量!
下面来分析global到底做了什么?
我们都知道php中的函数所产生的变量都是函数的私有变量,那么global关键字产生的变量也肯定逃不出这个规则,为什么这么说呢,看下面的代码:
<?php 
// 例子2 
function test() { 
global $a; 
unset($a); 
} 
$a = 1; 
test(); 
print $a; 
?>

复制代码
执行结果为:
1
为什么会输出1呢?不是已经把$a给unset了吗?unset失灵了?php的bug?
都不是,其实unset起作用了,是把test函数中的$a给unset掉了,可以在函数后面加入
print $a;
复制代码
来测试!也就是说global产生了test函数外部$a的别名变量“$a”,为了和外面的$a区别,我把它成为--test->$a,那么例子1也这么命名的话,可得出下面的图:
而test_globals执行过以后,看变量的变化:
此时,看图,就能理解为什么例子1执行完以后,$var2是0,而$var3是5了!
所以我们得出一个结论,在函数中global和$GLOBALS[]的区别在于:
global在函数产生一个指向函数外部变量的别名变量,而不是真正的函数外部变量,一但改变了别名变量的指向地址,就会发生一些意料不到情况(为什么会打印结果为2呢?其实就是因为$var1的引用指向了$var2的引用地址。导致实质的值没有改变。这时候只是指向$var1的指针指向了$var2的指针,只是指针指向变了一下,但是实质上根本就没有改变$var2的值,因此$var2的值仍旧不会变化),例如例子1.
$GLOBALS[]确确实实调用是外部的变量,函数内外会始终保持一致!
注:(接着回到上面的例子1,看test_global中的这一代码“$var2 =& $var1;”,上面是一个引用赋值运算,也就是$var2将指向var1所指向的物理内存地址,所以例子1执行过test_global函数以后,变量的变化只在函数的局部产生效应,在函数外部$var2的指向物理内存地址并没有变化,还是它自己.(重点)
接着回到上面的例子1,看test_global中的这一代码“$var2 =& $var1;”,上面是一个引用赋值运算,也就是$var2将指向var1所指向的物理内存地址,所以例子1执行过test_global函数以后,变量的变化由下图可以看出)
这一篇分析的不够透彻,不明白的请看《global和$GLOBALS[]的分析之二》其中举一反三通俗易懂
PHP 相关文章推荐
PHP+DBM的同学录程序(3)
Oct 09 PHP
phpmyadmin MySQL 加密配置方法
Jul 05 PHP
深入理解PHP原理之Session Gc的一个小概率Notice
Apr 12 PHP
微博短链接算法php版本实现代码
Sep 15 PHP
C/S和B/S两种架构区别与优缺点分析
Oct 23 PHP
PHP SplObjectStorage使用实例
May 12 PHP
php动态函数调用方法
May 21 PHP
变量在 PHP7 内部的实现(一)
Dec 21 PHP
PHP大文件分割上传 PHP分片上传
Aug 28 PHP
thinkPHP框架实现的简单计算器示例
Dec 07 PHP
php如何利用pecl安装mongodb扩展详解
Jan 09 PHP
阿里对象存储OSS在laravel框架中的使用方法
Oct 13 PHP
PHP开发者常犯的10个MySQL错误更正剖析
Jan 30 #PHP
PHP中全面阻止SQL注入式攻击分析小结
Jan 30 #PHP
几种有用的变型 PHP中循环语句的用法介绍
Jan 30 #PHP
通过PHP修改Linux或Unix口令的方法分享
Jan 30 #PHP
php代码收集表单内容并写入文件的代码
Jan 29 #PHP
php 无法加载mysql的module的时候的配置的解决方案引发的思考
Jan 27 #PHP
php木马webshell扫描器代码
Jan 25 #PHP
You might like
php printf输出格式使用说明
2010/12/05 PHP
PHP解析目录路径的3个函数总结
2014/11/18 PHP
textarea 控制输入字符字节数(示例代码)
2013/12/27 Javascript
js控制网页背景音乐播放与停止的方法
2015/02/06 Javascript
深入理解JavaScript系列(46):代码复用模式(推荐篇)详解
2015/03/04 Javascript
jQuery+ajax实现文章点赞功能的方法
2015/12/31 Javascript
jquery实现拖动效果
2016/08/10 Javascript
微信小程序 特效菜单抽屉效果实例代码
2017/01/11 Javascript
canvas实现图片根据滑块放大缩小效果
2017/02/24 Javascript
详解Vue.js之视图和数据的双向绑定(v-model)
2017/06/23 Javascript
微信小程序用户自定义模版用法实例分析
2017/11/28 Javascript
Vue调试神器vue-devtools安装方法
2017/12/12 Javascript
浅谈vue首屏加载优化
2018/06/28 Javascript
JavaScript设计模式之单例模式简单实例教程
2018/07/02 Javascript
深入理解js A*寻路算法原理与具体实现过程
2018/12/13 Javascript
layer提示框添加多个按钮选择的实例
2019/09/12 Javascript
基于JavaScript实现简单的轮播图
2021/03/03 Javascript
Python tempfile模块学习笔记(临时文件)
2014/05/25 Python
python里大整数相乘相关技巧指南
2014/09/12 Python
详解MySQL数据类型int(M)中M的含义
2016/11/20 Python
python中print()函数的“,”与java中System.out.print()函数中的“+”功能详解
2017/11/24 Python
Python查找第n个子串的技巧分享
2018/06/27 Python
对python以16进制打印字节数组的方法详解
2019/01/24 Python
python调用c++ ctype list传数组或者返回数组的方法
2019/02/13 Python
Python坐标线性插值应用实现
2019/11/13 Python
在Tensorflow中查看权重的实现
2020/01/24 Python
Python编程快速上手——正则表达式查找功能案例分析
2020/02/28 Python
什么是属性访问器
2015/10/26 面试题
医学生自荐信
2013/12/03 职场文书
践行三严三实心得体会
2014/10/13 职场文书
2014年物业管理工作总结
2014/11/21 职场文书
民政局标准版离婚协议书
2014/12/01 职场文书
2014年保险业务员工作总结
2014/12/23 职场文书
企业财务总监岗位职责
2015/04/03 职场文书
2015年机关后勤工作总结
2015/05/26 职场文书
合同补充协议书
2016/03/24 职场文书