位元詩人 [PHP] 程式設計教學:變數 (Variable)

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

程式 (program) 運行時,會將使用的資料 (data) 存在記憶體中。變數本身不是資料,而是指向資料的標籤。本文介紹 PHP 的變數。

宣告變數

PHP 的變數是大小寫敏感的。其命名規則如下:

  • 前綴使用 $ (dollar sign)
  • 首字使用英文字或底線
  • 接下來使用英文字、阿拉伯數字或底線
  • 不能用保留字 (keyword) 來命名變數

但 PHP 沒有 Perl 的變數前綴 (sigil) 規則,所有的變數前綴皆為 $

參考 (Reference)

參考會指向特定變數所指向的記憶體。修改參考可間接修改變數的值。像是以下例子:

<?php

$foo = 3;
$bar = &$foo;

$bar = 10;

10 == $foo or die("Wrong number");

在這個例子中,由於變數 $bar 是指向變數 $foo 的參考,修改 $bar 時,會間接修改 $foo

內建變數 (Predefined Variables)

PHP 有許多預先定義好的內建變數,這些變數可在 PHP 程式中立即使用。內建變數有一大部分和撰寫網頁程式相關。這裡有一份 PHP 內建變數的清單,讀者可以邊寫邊查,久了就會熟悉 PHP 的內建變數。

變數的可視域 (Scope)

理解變數的可視域相當重要,有時候一些不顯著的 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,如同原本預期的情形。

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 數的計算。

超全域變數 (Superglobal)

超全域變數是在所有 PHP 程式中都可以存取的變數。程式設計者無法在 PHP 程式中建立新的超全域變數。替代的方式是在 $GLOBALS 陣列中建立屬性。$GLOBAL 本身是 PHP 內建變數。其屬性在 PHP 程式中任一處皆可存取,不讀是函式內還是函式外。

$GLOBALS 中建立屬性的方式如下:

$GLOBALS["foo"] = 12345;

之後,讀入 $GLOBALS["foo"] 即可取得其值。

從外部來源取得的變數

這和網頁程式相關。像是 $_GET$_POST 陣列包含 HTML 表單送出的變數,$_COOKIE 陣列包含 cookie 儲存的變數。

宣告常數 (Constant)

內建函式 define 可用來宣告常數。常數在宣告後就不會再改變。試圖修改常數會引發程式錯誤。常數沒有前綴 $

以下 PHP 程式宣告圓周率:

define("PI", 3.1415927);

內建常數 (Predefined Constant)

PHP 提供多個內建常數,這些常數可以在程式中直接使用。這裡有一份內建常數的清單。讀者可以邊寫邊查,自然而然地熟悉這些常數。

魔術常數 (Magic Constant)

魔術常數提供和程式相關的資料。這些常數會根據情境,在編譯期自動轉成相對應的資料。以下是 PHP 的魔術常數:

  • __LINE__:在程式中的行數
  • __FILE__:檔案的路徑和檔名
  • __DIR__:檔案所在的目錄
  • __FUNCTION__:目前的函式名稱
  • __CLASS__:目前的類別名稱
  • __TRAIT__:目前的 trait 名稱
  • __METHOD__:目前的方法 (method) 名稱
  • __NAMESPACE__:目前的命名空間 (namespace)
  • ClassName::class:類別的全名
關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。