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生成带有雪花背景的验证码
Oct 09 PHP
php面向对象全攻略 (四)构造方法与析构方法
Sep 30 PHP
php中突破基于HTTP_REFERER的防盗链措施(stream_context_create)
Mar 29 PHP
php学习之变量的使用
May 29 PHP
php中使用Akismet防止垃圾评论的代码
Jun 10 PHP
phpcms手机内容页面添加上一篇和下一篇
Jun 05 PHP
WordPress网站性能优化指南
Nov 18 PHP
详解php中反射的应用
Mar 15 PHP
thinkphp框架下实现登录、注册、找回密码功能
Apr 06 PHP
php解析mht文件转换成html的实例
Mar 13 PHP
laravel 5.3中自定义加密服务的方案详解
May 09 PHP
PHP7导出Excel报ERR_EMPTY_RESPONSE解决方法
Apr 16 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
php实现文件下载实例分享
2014/06/02 PHP
php购物车实现方法
2015/01/03 PHP
PHP页面输出时js设置input框的选中值
2016/09/30 PHP
JQuery实现自定义对话框的代码
2008/06/15 Javascript
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
2011/11/30 Javascript
js获取select选中的option的text示例代码
2013/12/19 Javascript
排序算法的javascript实现与讲解(99js手记)
2014/09/28 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
2015/10/29 Javascript
全面解析Bootstrap弹窗的实现方法
2015/12/01 Javascript
详解jQuery Mobile自定义标签
2016/01/06 Javascript
jQuery时间插件jquery.clock.js用法实例(5个示例)
2016/01/14 Javascript
JavaScript数据结构链表知识详解
2016/11/21 Javascript
AngularJS使用ng-inlude指令加载页面失败的原因与解决方法
2017/01/19 Javascript
微信小程序之MaterialDesign--input组件详解
2017/02/15 Javascript
nodejs个人博客开发第二步 入口文件
2017/04/12 NodeJs
分析JavaScript数组操作难点
2017/12/18 Javascript
Vue 理解之白话 getter/setter详解
2019/04/16 Javascript
react用Redux中央仓库实现一个todolist
2019/09/29 Javascript
关于引入vue.js 文件的知识点总结
2020/01/28 Javascript
[16:27]DOTA2 HEROS教学视频教你分分钟做大人-艾欧
2014/06/11 DOTA
分享一个常用的Python模拟登陆类
2015/03/29 Python
简析Python的闭包和装饰器
2016/02/26 Python
Python实现将不规范的英文名字首字母大写
2016/11/15 Python
浅谈python和C语言混编的几种方式(推荐)
2017/09/27 Python
python3的输入方式及多组输入方法
2018/10/17 Python
Python面向对象之类的封装操作示例
2019/06/08 Python
Python高级特性之闭包与装饰器实例详解
2019/11/19 Python
关于python3.7安装matplotlib始终无法成功的问题的解决
2020/07/28 Python
安全承诺书范文
2014/03/26 职场文书
抽奖活动主持词
2014/03/31 职场文书
四年级评语大全
2014/04/21 职场文书
大学生工作自荐书
2014/06/16 职场文书
复兴之路纪录片观后感
2015/06/02 职场文书
初中体育教学随笔
2015/08/15 职场文书
Navicat for MySQL的使用教程详解
2021/05/27 MySQL
Arthas排查Kubernetes中应用频繁挂掉重启异常
2022/02/28 MySQL