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 sprintf()函数让你的sql操作更安全
Jul 23 PHP
Zend Guard一些常见问题解答
Sep 11 PHP
基于flush()不能按顺序输出时的解决办法
Jun 29 PHP
Java中final关键字详解
Aug 10 PHP
在WordPress中使用PHP脚本来判断访客来自什么国家
Dec 10 PHP
php reset() 函数指针指向数组中的第一个元素并输出实例代码
Nov 21 PHP
php基于SQLite实现的分页功能示例
Jun 21 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
Jun 16 PHP
PHP 结合 Boostrap 结合 js 实现学生列表删除编辑及搜索功能
May 21 PHP
Yii框架中用response保存cookie,用request读取cookie的原理解析
Sep 04 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
Feb 21 PHP
laravel ajax curd 搜索登录判断功能的实现
Apr 17 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中上传大体积文件时需要的设置
2006/10/09 PHP
用PHP实现多级树型菜单
2006/10/09 PHP
WordPress用户登录框密码的隐藏与部分显示技巧
2015/12/31 PHP
php微信浏览器分享设置以及回调详解
2016/08/01 PHP
PHP简单检测网址是否能够正常打开的方法
2016/09/04 PHP
php实现头像上传预览功能
2017/04/27 PHP
PHP开发中csrf攻击的简单演示和防范
2017/05/07 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
2019/06/06 PHP
javascript innerText和innerHtml应用
2010/01/28 Javascript
JavaScript获取网页、浏览器、屏幕高度和宽度汇总
2014/12/18 Javascript
使用jquery 简单实现下拉菜单
2015/01/14 Javascript
jquery 实现回车登录详解及实例代码
2016/10/23 Javascript
angular-ngSanitize模块-$sanitize服务详解
2017/06/13 Javascript
Vue2.0父组件与子组件之间的事件发射与接收实例代码
2017/09/19 Javascript
VsCode新建VueJs项目的详细步骤
2017/09/23 Javascript
在vue中使用公共过滤器filter的方法
2018/06/26 Javascript
axios向后台传递数组作为参数的方法
2018/08/11 Javascript
vue配置接口域名方法总结
2019/05/12 Javascript
如何利用nodejs自动定时发送邮件提醒(超实用)
2020/12/01 NodeJs
[00:52]DOTA2国际邀请赛
2020/02/21 DOTA
Django中模型Model添加JSON类型字段的方法
2015/06/17 Python
python 按照固定长度分割字符串的方法小结
2018/04/30 Python
python调用百度地图WEB服务API获取地点对应坐标值
2019/01/16 Python
Python中正反斜杠(‘/’和‘\’)的意义与用法
2019/08/12 Python
Python偏函数Partial function使用方法实例详解
2020/06/17 Python
Falconeri美国官网:由羊绒和羊毛制成的针织服装
2018/04/08 全球购物
印度最好的在线药品订购网站:PharmEasy
2018/11/30 全球购物
实习医生自我评价
2013/09/22 职场文书
大学生新闻专业个人自我评价
2013/11/12 职场文书
迎接领导欢迎词
2014/01/11 职场文书
大学学习生活感言
2014/01/18 职场文书
群众路线教育实践活动实施方案
2014/10/31 职场文书
群众路线自查报告及整改措施
2014/11/04 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书
高中语文教材(文学文化常识大全一)
2019/08/13 职场文书