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 相关文章推荐
Ajax PHP简单入门教程代码
Apr 25 PHP
php SQL防注入代码集合
Apr 25 PHP
详解PHP显示MySQL数据的三种方法
Jun 05 PHP
php 动态多文件上传
Jan 18 PHP
PHP中利用substr_replace将指定两位置之间的字符替换为*号
Jan 27 PHP
php实现12306火车票余票查询和价格查询(12306火车票查询)
Jan 14 PHP
PHP内存缓存Memcached类实例
Dec 08 PHP
php使用正则表达式获取图片url的方法
Jan 16 PHP
ThinkPHP简单使用memcache缓存的方法
Nov 15 PHP
ThinkPHP中create()方法自动验证表单信息
Apr 28 PHP
PHP测试框架PHPUnit组织测试操作示例
May 28 PHP
PHP设计模式之PHP迭代器模式讲解
Mar 22 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面向对象全攻略 (五) 封装性
2009/09/30 PHP
PHP PDOStatement:bindParam插入数据错误问题分析
2013/11/13 PHP
PHP中session变量的销毁
2014/02/27 PHP
JavaScript库 开发规则
2009/01/31 Javascript
JavaScript RegExp方法获取地址栏参数(面向对象)
2009/03/10 Javascript
js 方法实现返回多个数据的代码
2009/04/30 Javascript
扩展JavaScript功能的正确方法(译文)
2012/04/12 Javascript
javascript使用location.search的示例
2013/11/05 Javascript
jquery如何获取复选框的值
2013/12/12 Javascript
Jquery创建层显示标题和内容且随鼠标移动而移动
2014/01/26 Javascript
js转化毫秒为时间格式代码
2014/04/10 Javascript
jQuery窗口、文档、网页各种高度的精确理解
2014/07/02 Javascript
JavaScript 学习笔记之语句
2015/01/14 Javascript
原生js实现类似弹窗抖动效果
2015/04/02 Javascript
JS简单循环遍历json数组的方法
2016/04/22 Javascript
Angular2开发——组件规划篇
2017/03/28 Javascript
vue 中引用gojs绘制E-R图的方法示例
2018/08/24 Javascript
JS实现数组去重,显示重复元素及个数的方法示例
2019/01/21 Javascript
Vue匿名插槽与作用域插槽的合并和覆盖行为
2019/04/22 Javascript
Layui 动态禁止select下拉的例子
2019/09/03 Javascript
Vue组件通信中非父子组件传值知识点总结
2019/12/05 Javascript
jquery实现两个div中的元素相互拖动的方法分析
2020/04/05 jQuery
JavaScript用document.write()输出换行的示例代码
2020/11/26 Javascript
[01:03:36]Ti4 循环赛第三日DK vs Titan
2014/07/12 DOTA
Python 3.x读写csv文件中数字的方法示例
2017/08/29 Python
Python面向对象程序设计OOP深入分析【构造函数,组合类,工具类等】
2019/01/05 Python
python文件转为exe文件的方法及用法详解
2019/07/08 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
Python爬虫爬取微博热搜保存为 Markdown 文件的源码
2021/02/22 Python
HTML5中的网络存储实现方式
2020/04/28 HTML / CSS
ghd官网:英国ghd直发器品牌
2018/05/04 全球购物
System.Array.CopyTo()和System.Array.Clone()有什么区别
2016/06/20 面试题
电大自我鉴定范文
2013/10/01 职场文书
HR必备:超全面的薪酬待遇管理方案!
2019/07/12 职场文书
基于nginx实现上游服务器动态自动上下线无需reload的实现方法
2021/03/31 Servers
MongoDB数据库的安装步骤
2021/06/18 MongoDB