程式 (program) 運行時,會將使用的資料 (data) 存在記憶體中。變數本身不是資料,而是指向資料的標籤。本文介紹 PHP 的變數。
PHP 程式命名變數的規則如下:
$
(dollar sign)但 PHP 沒有 Perl 的變數前綴 (sigil) 規則,所有的變數前綴皆為 $
。
參考會指向特定變數所指向的記憶體。修改參考可間接修改變數的值。像是以下例子:
<?php
$foo = 3;
$bar = &$foo;
$bar = 10;
10 == $foo or die("Wrong number");
在這個例子中,由於變數 $bar
是指向變數 $foo
的參考,修改 $bar
時,會間接修改 $foo
。
PHP 有許多預先定義好的內建變數,這些變數可在 PHP 程式中立即使用。這些變數有一大部分和撰寫網頁程式相關。這裡有一份 PHP 內建變數的清單,讀者可以邊寫邊查,久了就會熟悉 PHP 的內建變數。
理解變數的可視域相當重要,有時候一些不顯著的 bug 就是未能理解可視域所造成。本節介紹 PHP 變數的可視域。
PHP 變數僅有單一可視域。也就是說,PHP 變數沒有區塊的概念。這項特性類似於 JavaScript 而和 C 相異。
例如,以下程式執行空的 for
迴圈,在程式執行後變數 $i
仍然存在:
<?php
for ($i = 1; $i <= 10; ++$i) {}
# Oops!
is_null($i) or die("\$i is available\n");
這是因為 PHP 沒有為 for
迴圈建立獨立的可視域,所以 for
迴圈結束後,變數 $i
仍然存在。
如果真在要建立獨立的可視域的話,可以使用 IIFE (立即執行函式) 模式:
<?php
# IIFE pattern in PHP 7+.
(function () {
for ($i = 1; $i <= 10; ++$i) {}
})();
is_null($i) or die("\$i is available\n");
技術上來說,這個程式建立一個匿名函式 (anonymous function)。該函式建立完後立即執行。
實際上 PHP 程式甚少使用 IIFE 模式,比較簡單的方式是每次要使用變數前都確實地賦值,就不需在意該變數先前是否有使用過。
global
變數由於函式有獨立的可視域,以下程式不會照預想的方式來執行:
<?php
$a = 3;
$b = 4;
function sum()
{
return $a + $b;
}
# Oops!
7 == sum() or die("Wrong value");
這是因為函式的可視域是獨立的,不會讀入 $a
和 $b
。
如果想在函式中讀入外部變數,可使用保留字 global
:
<?php
$a = 3;
$b = 4;
function sum()
{
global $a, $b;
return $a + $b;
}
7 == sum() or die("Wrong value");
這時候函式會讀入 $a
和 $b
,如同原本預期的情形。
$GLOBALS
本身是 PHP 內建變數。該變數是 PHP 陣列 (array),其屬性在 PHP 程式中任一處皆可存取,不讀是函式內還是函式外。
在 $GLOBALS
中建立屬性的方式如下:
$GLOBALS["foo"] = 12345;
之後,讀入 $GLOBALS["foo"]
即可取得其值。
static
變數每次函式執行時,內部狀態會重新運算。若想在函式呼叫時儲存其狀態,可使用保留字 static
。
以下範例函式 fib
內的變數 $a
和 $b
會在每次函式執行後儲存下來。所以每次回傳值皆相異:
<?php
# Fibonacci numbers.
function fib()
{
static $a = 1, $b = 1;
$result = $a;
$c = $a + $b;
$a = $b;
$b = $c;
return $result;
}
for ($i = 0; $i < 20; ++$i) {
echo fib() . "\n";
}
這個程式利用這項特性來進行 Fibonacci 數的計算。
內建函式 define
可用來宣告常數。常數在宣告後就不會再改變。試圖修改常數會引發程式錯誤。常數沒有前綴 $
。
以下 PHP 程式宣告圓周率:
define("PI", 3.1415927);