PHP语言中global和$GLOBALS[]的分析 之二


Posted in PHP onFebruary 02, 2012

还是借用上一篇的例子:

PHP代码

<?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的原理!
我们都知道变量其实是相应物理内存在代码中的”代号”而已
引用php手册的$GLOBALS的解释:
Global 变量:$GLOBALS,注意: $GLOBALS 在 PHP 3.0.0 及以后版本中适用。
由所有已定义全局变量组成的数组。变量名就是该数组的索引。这是一个“superglobal”,或者可以描述为自动全局变量。
也就是说上面代码中的$var1和$GLOBALS['var1']是指的同一变量,而不是2个不同的变量!
下面来分析global到底做了什么?
引用php手册的global的解释:
如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。
我们都知道php中的函数所产生的变量都是函数的私有变量,那么global关键字产生的变量也肯定逃不出这个规则,为什么这么说呢,看下面的代码:
PHP代码

<?php 
// 例子2 
function test() { 
global $a; 
unset($a); 
} 
$a = 1; 
test(); 
print $a; 
?>

执行结果为:
1
为什么会输出1呢?不是已经把$a给unset了吗?unset失灵了?php的bug?
都不是,其实unset起作用了,是把test函数中的$a给unset掉了,可以在函数test()中加入
print $a;
来测试!
接着回到上面的例子1,看test_global中的这一代码“$var2 =& $var1;”,上面是一个引用赋值运算,也就是$var2将指向var1所指向的物理内存地址,所以例子1执行过test_global函数以后,变量的变化只在函数的局部产生效应,在函数外部$var2的指向物理内存地址并没有变化,还是它自己.
此时,就能理解为什么例子1执行完以后,$var2是0,而$var3是5了!
所以我们得出一个结论,在函数中global和$GLOBALS[]的区别在于:
global在函数产生一个指向函数外部变量的别名变量,而不是真正的函数外部变量,一但改变了别名变量的指向地址,就会发生一些意料不到情况,例如例子 1.
$GLOBALS[]确确实实调用是外部的变量,函数内外会始终保持一致
可以对照 下面两个列子再加深下印象:
global:
<?php 
function myfunction(){ 
global $bar; 
unset($bar); 
} 
$bar=”someting”; 
myfunction(); 
echo $bar; 
?>

输出:someting
$GLOBALS[]:
<?php 
function foo() 
{ 
unset($GLOBALS['bar']); 
} 
$bar = “something”; 
foo(); 
echo $bar; 
?>

输出:空
当按照上面的思路理解后,碰到下面的情况是不是又有些晕呢?
<?php 
$a = 1; 
$b = 2; 
function Sum() 
{ 
global $a, $b; 
$b = $a + $b; 
} 
Sum(); 
echo $b; 
?>

输出将是 “3″。在函数中申明 了全局变量 $a 和 $b,任何变量的所有引用变量都会指向到全局变量。
怎么不是2呢,在函数外部不是不影响吗,请注意$b在函数中并没有通过引用修改,而是修改的$b指向物理内存的值,因此外部输入为3。
PHP 相关文章推荐
php实现mysql同步的实现方法
Oct 21 PHP
PHP 手机归属地查询 api
Feb 08 PHP
php获取post中的json数据的实现方法
Jun 08 PHP
PHP异步调用socket实现代码
Jan 12 PHP
PHP可逆加密/解密函数分享
Sep 25 PHP
ThinkPHP做文字水印时提示call an undefined function exif_imagetype()解决方法
Oct 30 PHP
php使用date和strtotime函数输出指定日期的方法
Nov 14 PHP
php设计模式之单例模式代码
Jun 11 PHP
Laravel 5.1 on SAE环境开发教程【附项目demo源码】
Oct 09 PHP
php socket通信简单实现
Nov 18 PHP
Redis在Laravel项目中的应用实例详解
Aug 11 PHP
PHP如何防止XSS攻击与XSS攻击原理的讲解
Mar 22 PHP
php中global和$GLOBALS[]的分析之一
Feb 02 #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
You might like
初学者入门:细述PHP4的核心Zend
2006/09/05 PHP
PHP逐行输出(ob_flush与flush的组合)
2012/02/04 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
table标签的结构与合并单元格的实现方法
2013/07/24 PHP
php数字运算验证码的实现代码
2015/07/30 PHP
php生成图片缩略图功能示例
2017/02/22 PHP
PHP常见过waf webshell以及最简单的检测方法
2019/05/21 PHP
在JavaScript中遭遇级联表达式陷阱
2007/03/08 Javascript
用js判断浏览器是否是IE的比较好的办法
2007/05/08 Javascript
通过隐藏option实现select的联动效果
2009/11/10 Javascript
浅析jquery unbind()方法移除元素绑定的事件
2016/05/24 Javascript
BootStrap入门教程(三)之响应式原理
2016/09/19 Javascript
node.js文件上传处理示例
2016/10/27 Javascript
Vue.js实现文章评论和回复评论功能
2020/05/30 Javascript
微信小程序图片宽100%显示并且不变形
2017/06/21 Javascript
关于vue.extend和vue.component的区别浅析
2017/08/16 Javascript
尝试自己动手用react来写一个分页组件(小结)
2018/02/09 Javascript
js中Array对象的常用遍历方法详解
2019/01/17 Javascript
vue 组件之间事件触发($emit)与event Bus($on)的用法说明
2020/07/28 Javascript
微信小程序实现音乐播放页面布局
2020/12/11 Javascript
[04:44]显微镜下的DOTA2第二期——你所没有注意到的细节
2014/06/20 DOTA
Python 冒泡,选择,插入排序使用实例
2015/02/05 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
2020/03/12 Python
python tkinter GUI绘制,以及点击更新显示图片代码
2020/03/14 Python
Python分析微信好友性别比例和省份城市分布比例的方法示例【基于itchat模块】
2020/05/29 Python
详解CSS3+JS完美实现放大镜模式
2020/12/03 HTML / CSS
《理想》教学反思
2014/02/17 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
群众路线个人整改措施
2014/10/24 职场文书
2014年纪检部工作总结
2014/11/12 职场文书
民间借贷借条如何写
2015/05/26 职场文书
在校证明模板
2015/06/17 职场文书
2015中秋祝酒词
2015/08/12 职场文书
幼儿园国培研修日志
2015/11/13 职场文书
初中美术教学反思
2016/02/17 职场文书
JS中forEach()、map()、every()、some()和filter()的用法
2022/05/11 Javascript