php中global和$GLOBALS的區別分析

PHP 的全局變量和 C 語言有一點點不同,在 C 語言中,全局變量在函數中自動生效,除非被局部變量覆蓋,這可能引起一些問題,有些人可能漫不經心的改變一個全局變量。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"; 
?> 

複製代碼 
執行結果爲: 


怎麼會這樣呢?不應該是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呢?不是已經把$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函數以後,變量的變化由下圖可以看出) 
還是借用上一篇的例子: 

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”; 
?> 

執行結果爲: 


怎麼會這樣呢?不應該是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呢?不是已經把$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


文章轉自:http://www.jb51.net/article/29584.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章