1. 程式人生 > >搞定PHP面試 - 變數知識點整理

搞定PHP面試 - 變數知識點整理

一、變數的定義

1. 變數的命名規則

變數名可以包含字母、數字、下劃線,不能以數字開頭。

$Var_1 = 'foo'; // 合法
$var1 = 'foo'; // 合法
$_var1 = 'foo'; // 合法
$Var-1 = 'foo'; // 非法,不能包含 -
$1_var = 'foo'; // 非法,不能以數字開頭
在此所說的字母是 a-z,A-Z,以及 ASCII 字元從 127 到 255(0x7f-0xff)。
因此實際上使用中文變數名也是合法的。
甚至使用中文的標點符號作為變數名都是合法的。
只是一般都不推薦這樣用。
$姓名 = 'foo'; // 合法
$?。…… = 'foo'; // 合法。

變數名區分大小寫

$var = 'Bob';
$Var = 'Joe';
echo "$var, $Var";      // 輸出 "Bob, Joe"

$this 是一個特殊的變數,它不能被賦值

$this = 'foo'; // Fatal error: Cannot re-assign $this

2. 變數的賦值

變數的引用賦值與傳值賦值詳情傳送門: 變數的引用賦值與傳值賦值

傳值賦值

變數預設總是傳值賦值。那也就是說,當將一個表示式的值賦予一個變數時,整個原始表示式的值被賦值到目標變數。
這意味著,例如,當一個變數的值賦予另外一個變數時,改變其中一個變數的值,將不會影響到另外一個變數。

$foo = 'Bob';     // 將 'Bob' 賦給 $foo
$bar = $foo;      // 通過 $foo 傳值賦值給 $bar
$bar = 'Jack';        // 修改 $bar 變數
echo $foo;          // $foo 的值未改變,依然是 'Bob'

引用賦值

引用賦值,就是新的變數簡單的引用(換言之,“成為其別名” 或者 “指向”)了原始變數。
改動新的變數將影響到原始變數,反之亦然。

使用引用賦值,只需要將一個 & 符號加到將要賦值的變數前(源變數)

$foo = 'Bob';        // 將 'Bob' 賦給 $foo
$bar = &$foo;     // 通過 $bar 引用 $foo
$bar = 'Jack';     // 修改 $bar 變數
echo $foo;           // $foo 的值也被修改為 'Jack'
只有有名字的變數才可以引用賦值
$foo = 25;
$bar = &$foo;      // 合法的賦值
$bar = &(24 * 7);  // 非法; 引用沒有名字的表示式

function test()
{
   return 25;
}

$bar = &test();    // 非法

3.變數的初始化

雖然在 PHP 中並不需要初始化變數,但對變數進行初始化是個好習慣。

未初始化的變數的預設值

未初始化的變數具有其型別的預設值。

  • 布林型別的變數預設值是 FALSE
  • 整形和浮點型變數預設值是 0
  • 字串型變數預設值是空字串 ""
  • 陣列變數的預設值是空陣列 array()

4. 可變變數

可變變數是指變數的變數名可以動態的設定和使用。

一個可變變數獲取了一個普通變數的值作為這個可變變數的變數名。在下面的例子中 hello 使用了兩個美元符號($)以後,就可以作為一個可變變數的變量了。

$a = 'hello';

$$a = 'world';

這時,兩個變數都被定義了:$a 的內容是“hello”並且 $hello 的內容是“world”。

因此,以下語句:

echo "$a ${$a}";

與以下語句輸出完全相同的結果:

echo "$a $hello";

它們都會輸出:hello world。

可變變數用於陣列

要將可變變數用於陣列,必須解決一個模稜兩可的問題。
這就是當寫下 $$a[1] 時,解析器需要知道是想要 $a[1] 作為一個變數呢,還是想要 $ $a 作為一個變數並取出該變數中索引為 [1] 的值。
解決此問題的語法是,對第一種情況用 ${$a[1]},對第二種情況用 ${$a}[1]

可變變數用於類

類的屬性也可以通過可變屬性名來訪問。可變屬性名將在該呼叫所處的範圍內被解析。
例如,對於 $foo->$bar 表示式,則會在本地範圍來解析 $bar 並且其值將被用於 $foo 的屬性名。
對於 $bar 是陣列單元時也是一樣。

也可使用花括號{}來給屬性名清晰定界。
最有用是在屬性位於陣列中,或者屬性名包含有多個部分或者屬性名包含有非法字元時(例如來自 json_decode()SimpleXML)。

將一個json格式的字串轉換成php物件:


$string = '{"os-version":"10.3.1","1day":24}';
$obj = json_decode($string);
print_r($obj);

輸出結果:


stdClass Object
(
    [os-version] => 10.3.1
    [1day] => 24
)

此時若想訪問物件$obj 中的 os-version屬性或1day屬性,若直接使用 $obj->os-version$obj->1day 訪問的話一定會報錯。

正確的訪問方式:


echo $obj->{"os-version"};
echo '<br/>';
echo $obj->{"1day"};

輸出結果:


10.3.1
24

二、變數的作用域和靜態變數

1. 變數的作用域

變數的作用域也稱變數的範圍,即它定義的上下文背景(也就是它的生效範圍)。
php變數的範圍跨度同樣包含了include和require引入的檔案。

區域性變數

在使用者自定義函式中,將引入一個區域性函式範圍。任何用於函式內部的變數的作用域都將被限制在區域性函式範圍內。例如:

$outer = 'str'; /* 全域性範圍 */

function myfunc()
{
    echo $outer; /* 對區域性範圍變數的引用 */
}

myfunc();

這個指令碼不會有任何輸出,因為 echo 語句引用了一個區域性版本的變數 $outer,而且在這個範圍內,它並沒有被賦值。

全域性變數

global關鍵字


$outer = 'str'; // 全域性

function myfunc()
{
    global $outer;
    echo $outer; // 區域性
}
myfunc();

這個指令碼會輸出 str。在函式中使用global關鍵字聲明瞭全域性變數 $a$b 之後,對任一變數的所有引用都會指向其全域性版本。對於一個函式能夠宣告的全域性變數的最大個數,PHP 沒有限制。

$GLOBALS超全域性陣列

$GLOBALS — 引用全域性作用域中可用的全部變數


$outer = 'str'; // 全域性

function myfunc()
{
    echo $GLOBALS['outer'];
}
myfunc();

這個指令碼會輸出 str$GLOBALS 是一個關聯陣列,每一個變數為一個元素,鍵名對應變數名,值對應變數的內容。$GLOBALS 之所以在全域性範圍內存在,是因為 $GLOBALS 是一個超全域性變數。

超全域性變數

PHP 中的許多預定義變數都是“超全域性的”,這意味著它們在一個指令碼的全部作用域中都可用。在函式或方法中無需執行 global $variable; 就可以訪問它們。

這些超全域性變數是:

$GLOBALS — 超全域性變數是在全部作用域中始終可用的內建變數
$_SERVER — 伺服器和執行環境資訊
$_GET — HTTP GET 變數
$_POST — HTTP POST 變數
$_FILES — HTTP 檔案上傳變數
$_COOKIE — HTTP Cookies
$_SESSION — Session 變數
$_REQUEST — HTTP Request 變數。預設情況下包含了 $_GET$_POST$_COOKIE 的陣列。
$_ENV — 環境變數

2. 靜態變數

變數範圍的另一個重要特性是靜態變數(static variable)。
靜態變數僅在區域性函式域中存在,但當程式執行離開此作用域時,其值並不會消失。

靜態變數的特點

1.使用static關鍵字修飾
2.靜態宣告是在編譯時解析的
3.僅初始化一次
4.初始化時需要賦值
5.每次執行函式該值會保留
6.static修飾的變數是區域性的,僅在函式內部有效
7.可以記錄函式的呼叫次數,從而可以在某些條件下終止遞迴。


function myFunc()
{
    static $a = 1;
    echo $a++;
}
myFunc(); // 1
myFunc(); // 2
myFunc(); // 3

變數 $a 僅在第一次呼叫 myFunc() 函式時被初始化,之後每次呼叫 myFunc() 函式都會輸出 $a 的值並加1。

宣告靜態變數時不能用表示式的結果對其賦值


function foo(){
    static $int = 0;        // 正確
    static $int = 1+2;       // 錯誤  (使用表示式的結果賦值)
    static $int = sqrt(121);      // 錯誤  (使用表示式的結果賦值)

    echo $int++;
}

靜態變數與遞迴函式

靜態變數提供了一種處理遞迴函式的方法。
遞迴函式是一種呼叫自己的函式。寫遞迴函式時要小心,因為可能會無窮遞迴下去。必須確保有充分的方法來中止遞迴。
以下這個簡單的函式遞迴計數到 10,使用靜態變數 $count 來判斷何時停止:


function test()
{
    static $count = 0;

    $count++;
    echo $count;
    if ($count < 10) {
        test();
    }
    $count--;
}

3. 例項分析

寫出如下程式的輸出結果


$count = 5;
function get_count()
{
    static $count;
    return $count++;
}

echo $count;
++$count;

echo get_count();
echo get_count();

第8行 echo $count; 輸出 5

第9行 ++$count;,此時 $count 的值為 6

第11行 echo get_count();,第一次呼叫 get_count() 函式

function get_count()
{
    // 宣告靜態變數 $count,由於為賦值,所以其值為 NULL
    static $count;
    // $count++,先返回 $count 的值,後自增。因此,返回值為 NULL。
    // NULL 自增後的值為 1,因此,自增後的 $count = 1
    return $count++;
}

第一次呼叫 get_count() 的返回值為 NULL,而 echo NULL; 什麼都不會輸出。

第12行 echo get_count();,第二次呼叫 get_count() 函式

function get_count()
{
    // 第二次呼叫時,該行不會執行
    static $count;
    // 此前 $count = 1,$count++,先返回 $count 的值,後自增。因此,返回值為 1。
    return $count++;
}

第一次呼叫 get_count() 的返回值為 1,而 echo get_count(); 輸出 1

整個程式的輸出結果為 51

原文地址:https://segmentfault.com/a/1190000016291982