2019年11月13日 星期三

網頁技術速學筆記 (五) : PHP 動態網頁 (1)

寫完 HTML 表單筆記後, 網頁前端部分應該大致完成了, 接下來是後端動態網頁的產出部分, 因最近在整理搬遷之前寫的 PHP 專案, 所以就順便把 PHP 筆記也整理一下吧.

PHP 是我學習動態網頁設計的第二個語言 (第一個是 ASP), 動機之一是因為它比 ASP 功能強很多, 特別是可用 cURL 來寫爬蟲程式; 其次是 PHP 一直是虛擬主機業者最普遍提供的運算環境, 即所謂的 LAMP (Linux + Apache + MySQL + PHP) 環境.

本系列之前的筆記參考 :

申請免費 PHP 虛擬主機 000a.biz 與 000webhost.com
網頁技術速學筆記 (一) : HTML 基礎
網頁技術速學筆記 (二) : CSS 基礎
網頁技術速學筆記 (三) : Javascript 基礎
# 網頁技術速學筆記 (四) : HTML 表單

關於 PHP 語言的背景摘要整理如下 :
  1. PHP 是加拿大人 Rasmus Lerdorf 所設計的一種網頁後端語言, 最初用來偵測其履歷有多少人閱覽. PHP 程式碼以 .php 為副檔名, 可嵌入 HTML 碼直接輸出網頁. 
  2. PHP 是直譯式跨平台語言, 可以在 UNIX, Linux, Windows, Mac OS 等作業系統下, 不須編譯成二進位檔就可執行. 在 PHP 4.2 以後可以直接透過命令列執行, 不須透過網站伺服器. PHP 也可以開發視窗應用程式 (例如 PHP GTK).
  3. PHP 的語法吸收了 C, Java, 以及 Perl 等語言的優點. 
參考 :

# Wiki : PHP

目前大部分虛擬主機都以 PHP 為主要的執行環境, 例如 000a.biz 與 000webhost.com 所提供的免費主機都是執行 PHP 的運算環境, 參考 :


在 Windows 上布置 PHP 後端執行環境最方便的是 XAMPP 安裝包, 也可以下載免安裝版, 只要解開 zip 檔執行 xampp-control.exe 即可手動啟動 Apache 與 MySQL 伺服器, 馬上可執行 PHP 程式, 參考 :

安裝 XAMPP PHP 架站工具包

也可以利用線上 PHP 測試網站來學習 PHP, 例如 :

http://www.writephponline.com/

此網站不須註冊, 馬上可輸入 PHP 程式碼進行測試.


一. 在 HTML 檔中嵌入 PHP 程式碼 :

PHP 程式檔內容由 HTML 碼以及被 <?php 與 ?> 包圍起來的 PHP 程式碼組成, 存檔時要存成以 .php 為副檔名之檔案, 例如 :

<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <meta charset="utf-8">
</head>
<body>
<?php                     //PHP 程式開頭
 echo "Hello World"
?>                           //PHP 程式結束
</body>
</html>

伺服器在讀取此檔案時會先執行其中被 <?php 與 ?> 包圍起來的 PHP 程式碼, 運算結果嵌入原位置與 HTML 碼一起輸出回應給客戶端.

在一個 PHP 檔案中, 可以有多個 <?php 與 ?> 區段, 不須將所有 PHP 程式碼放在一個 <?php 與 ?> 區段內. <?php 與 ?> 區段可以放在網頁中的任何位置.

PHP 敘述必須以分號結尾, PHP 解譯器讀取一個指令後, 會一直往下讀取, 直到遇到分號為止作為一個敘述, 再進行解譯是否符合語法, 因此敘述可能跨好幾行. 

如果將 PHP 副檔名改為 .phps, 則在瀏覽器中瀏覽該檔案時會顯示原始碼, 適合用來做為程式分享.


二. 註解與輸出 :

PHP 的註解方式有兩種 :
  1. 單行註解 : 在 // 後面的程式碼會被視為註解而不被解譯
  2. 多行註解 : 在 /* 與 */ 之間的程式碼會被視為註解而不被解譯
但是特別注意, 多行註解內部不可再有多行註解, 否則會因形成巢狀註解而出現編譯錯誤. 善用註解可使程式碼易於維護.

PHP 有三個輸出字串到網頁的指令 : echo, print, 以及 printf. 其中 echo 與 print 是建構式 (language construct), 不是函數, 因此使用時不需要小括弧, 例如 echo "輸出 $str", 但加上括弧也可以, 例如 echo("輸出 $str"). 而 printf 則是函數.

echo 與 print/printf 的差別是 : 
  • print 有傳回值, 成功傳回 TRUE/1, 失敗傳回 FALSE/0
  • echo 與 printf 沒有傳回值. 
  • echo/printf 可以輸出多個變數, 而 print 則只能輸出一個變數. 
  • echo 的執行速度較快. 
  • print 可用在可變函數. 
最常用的是 echo, 但它無法直接輸出陣列內容 (只顯示 'Array' 而已), 只能輸出單一陣列元素, 因此須靠迴圈遍歷陣列元素, 直接輸出陣列內容與結構必須用 print_r() 或 var_dump() 函式.


1. 用 echo 建構式輸出字串 : 

echo 建構式可以輸出一個或多個參數 (用逗號隔開), 參數可用變數或字串, PHP 的字串可用單引號或雙引號, 例如 :

echo "Hello World!";
echo "Hello", "World!";

也可以輸出有跳行的長字串 :

echo "Hello
         World!";

可以在 echo 中輸出變數, 若變數放在引號中, 一定要用雙引號才會對變數進行解析進行代換, 例如 :

$x=100;
echo "變數", "x的值", "等於", $x, "<br>";
echo "變數", "x的值", "等於", "$x", "<br>";
echo "變數", "x的值", "等於", '$x', "<br>";   //單引號內的變數不會代換

輸出如下, 其中第二個 echo 的 $x 變數放在雙引號中, 因此會進行解析代換, 但第三個 echo 則不會代換, 把 $x 當成字元輸出 :

變數x的值等於100
變數x的值等於100
變數x的值等於$x

也可以用 "." 運算子串接要輸出的字串, 例如 :

echo "變數"."x的值"."等於$x";      //輸出 "變數x的值等於100"

PHP 也像 ASP 一樣在單行輸出中提供等號 "=" 代替 echo 的簡寫法, 下面兩種寫法是一樣的 (不建議用簡寫法), 例如 :

<? =$x ?>  
<? echo $x ?>


2. 用 print 建構式輸出字串 : 

print 功能與 echo 相同, 都是建構式不是函式, 兩者差別是 print 只有一個參數, 不能像 echo 那樣用逗號輸出多個參數, 例如 :

$x=100;
print "變數x的值等於$x"; //輸出 "變數x的值等於100"


3. 用 printf() 函式輸出字串 : 

printf() 函式用來輸出格式化字串 (無傳回值), 類似 C 語言中的 printf() 函數功能, 其介面為 :

printf(格式化字串, 變數1, 變數2, 變數3, ....)

第一參數為含有格式字元的格式化字串, 分別對應後面與格式字元相同個數的多個變數. 格式字元種類如下表 :  


 格式字元 說明
 %b 顯示二進位整數
 %c 顯示字元
 %d 顯示有正負號的整數
 %u 顯示無正負號的整數
 %f 顯示浮點數
 %o 顯示8進位整數
 %s 顯示字串
 %x 顯示小寫的 16 進位整數
 %X 顯示大寫的 16 進位整數


例如 :

$a=100;
$b="銅板";
printf("我有%d個%s", $a, $b); //輸出 "我有100個銅板"

PHP 的語言建構式還有如下這些 :

die() echo() empty() exit() eval()
include() include_once() isset() list() require()
require_once() return() print() unset()

這些名稱也是保留字, 不可用作識別字.


三. 資料型態 :

PHP 是弱型別動態語言, 變數宣告時不需指定資料型態, 解譯器是在執行指派運算時依據字面值 (literal) 或運算結果動地決定變數之資料型別. 內建資料型態有 8 種 :


 PHP 資料型態 說明
 boolean 布林值有 TRUE/1, FASLE/0 兩個值 (不分大小寫)
 integer 有號整數, 預設十進位, 前面冠 0 為八進位, 冠 0x 為十六進位
 float 浮點數 (精確度14 位小數), 可用 e 或 E 科學表示法
 string 字串 (單或雙引號), 含 \n, \r, \t, \\, \$, \", \nnn, \xnn 等逸出字元
 array 支援關聯式陣列, 鍵可以是整數或字串, 值可以是任何型別
 object 物件, 支援物件導向設計, 屬性與方法使用 -> 運算子存取
 resource 外部資源的參考, 例如 XML 剖析器, 檔案, 或資料庫
 NULL 未賦值的變數值為 NULL, 或呼叫 unset() 後之變數值


任何變數未賦值前之值均為 NULL, 已賦值之變數可用 unset() 清除其值設為 NULL, 呼叫 isset() 則可檢查變數是否有賦值, 傳回 TRUE 表示有賦值, 傳回 FALSE 表示其值為 NULL, 這在檢查前端網頁的表單元件是否有送出值時常用到.


四. 變數 :

PHP 是動態語言, 變數名稱不用事先指定資料型態, 而是在執行時才依據賦值動態地決定其型態, 因此變數可隨時重新指定為另一種資料型態之值. 但唯一的例外是 $this, 這是一個用來表示 PHP 物件本身的特別變數, 不可重新指定其值.


1. 識別字 (identifier) :

識別字包括變數與函數名稱, 其命名規則如下 : 
  • 變數名稱必須以 $ 開頭, 後接任何數目的英數字或底線組合.
  • $ 後第一個字元不可以是數字, 必須是英文字母或底線, 第二字元以後才可以用數字, 最好只用英數字與底線, 不可用 $, @ 等特殊符號. 故 $var@1 與 $va$r 均不合法, 但 ${1}, ${"變數"} 則是合法.
  • 變數名稱有分大小寫, 故 $var 與 $Var 乃不同變數.
  • 不可以使用 PHP 保留字, 內建變數, 內建函數, 或內建物件名稱當變數名稱.
注意, 要避免在內部範圍 (例如迴圈或函數內) 使用與外部範圍同樣的名稱, 以免存取錯誤.

整體來說 PHP 對於大小寫採雙軌制, 有一部分是很確定有分大小寫, 例如變數名稱有分大小寫; 有一部分是可選擇的, 例如常數可在宣告時選擇要不要分大小寫; 還有一部分是不分大小寫的, 例如保留字與內建函式名稱都被 PHP 保留了, 不管大小寫都被保留了, 使用者不能使用, 因此 PHP 不管其大小寫都可順利解譯.

保留字例如宣告常數使用 define("PI", 3.14159), deFine("PI", 3.14159) 或 DEFINE("PI", 3.14159) 都可以. 內建函式與指令也都不分大小寫, 例如 IF, iF, If, 或 if 都可以正常執行. 但為了一致性, 保留字與內建函式建議均使用小寫.


2. 變數的有效範圍 (scope) :

PHP 的變數依其有效範圍可分為區域, 全域, 以及靜態變數 :

(1). 區域變數 :

區域變數是在函式內宣告的變數 (包括函式的參數), 只能在函式內部使用, 在函式外無法存取. 當呼叫函式時, 區域變數會被建立, 函式執行完畢即被釋放, 即區域變數的值不會被保留, 例如 :

function myFunc() {
  $a=2; //宣告區域變數
  echo "函式內 a=$a";
  }
myFunc(); //顯示 "函式內 a=2"
echo "函式外 a=$a"; //顯示 "函式外 a=" (全域變數 $a 不存在)

此例中呼叫 myFunc() 時會印出函式內的區域變數 $a=2, 但在函式外卻無法存取 $a, 因為找不到全域變數 $a 因此沒有印出值.


(2). 全域變數 :

全域變數是在函式外面宣告的變數, 在整個 PHP 檔案中都可以使用, 但是它不像 Javascript 一樣自動穿透到函式內部, PHP 全域變數有效範圍只限於主程式中, 不會影響到函式內同名的區域變數, 欲在函式內部存取全域變數時必須在變數前面加上 global 關鍵字, 例如 : 

$a=2; //宣告全域變數
function myFunc() {
  global $a=3; //宣告 $a 為全域變數
  echo "函式內 a=$a";
  }
myFunc(); //顯示 "函式內 a=3"
echo "函式外 a=$a"; //顯示 "函式外 a=3"

在函式內存取全域變數的第二個方法是使用 PHP 特別定義的陣列 $GLOBAL["全域變數名"], 例如 :

$a=2;
function myFunc() {
echo "函式內 a=".$GLOBAL["a"];
}

注意, 雖然 PHP 的全域變數沒有穿透性, 但為了避免混淆, 最好不要在函式內部使用與外部一樣名稱的變數.


(3). 靜態變數 :

靜態變數只能在函式內用 static 關鍵字宣告, 使宣告於函式內之變數在呼叫結束後, 仍然存在於記憶體, 不會被釋放, 下一次在呼叫此函數時, 會重新被存取到. 只要函式被呼叫一次, 函式內的靜態變數就會一直存在, 但是它與全域變數不同的是, 於函式外部是無法存取得到靜態變數的, 例如 :

function myFunc() {
  static $msg; //宣告靜態變數
  $msg += 1;
  echo $msg;
  }
myFunc(); //顯示 1
myFunc(); //顯示 2
echo "函式外 msg=$msg"; //顯示 "函式外 msg="

注意, 靜態變數不能與複合運算子同時使用, 例如 :

static $msg += 1; //syntax error
應該分開來 :
static $msg;
$msg += 1;


3. 變數的預設值 :

PHP 每一種資料型態都有預設值如下 :


 變數型態 預設值
 整數, 浮點數  0
 字串 "" (空字串)
 布林值 FALSE
 陣列 空陣列

例如 :

echo "x=$x"; //輸出 x= 
echo $y += 10; //輸出 10

第一個 echo 因變數 $x 尚未賦值, 在字串中故預設值為空字串. 第二個 echo 因變數 $y 之前尚未賦值, 因為用於算式中, 故預設值為 0.


4. 參照指派 (assign by reference) : 

所謂參照指派是用參照運算子 & 於變數 $var 前 (即 &$var), 這樣就會取得該變數之儲存位址, 可用於傳址呼叫. 注意, 對參照指派變數 &$var 賦值同時也會改變 $var 之值, 因為它們都指向相同位址. 例如 :

$var1="Peter";
$var2=&$var1; //使用參照運算子 & 取得 $var1 之位址指派給 $var2
$var2="John"; //賦值 $var2 ($var1 也會同步被改)
echo $var1; //輸出 "John"
echo $var2; //輸出 "John"

此處 $var1 與 $var2 指向相同位址, 因此變更 $var2 之值也會變更 $var1 之值.


5. 可變變數 (variable variables) :   

PHP 的可變變數可以動態地設定變數名稱, 它是以另外一個變數的值來作為它的變數名稱, 語法是在一個字串變數名稱 $var 前面再加一個 $ 為 $$var, 表示以 $var 之值作為其名稱的一個變數, 例如 :

$x="hello";
$$x="world"; //此指令等同於 $hello="world"
echo "$x $$x"; //輸出 hello $hello 

此處因雙引號的變數解析功能只能用一次, 因此 $$x 只解析了 $x 為 hello, 因此輸出 hello $hello, 若要突破雙引號的一次解析限制, 必須用大括號將變數括起來 : 

echo "$x ${$x}"; //輸出 hello world

6. 與變數操作有關的內建函式 : 




五. 常數 :

PHP 使用內建函數 define() 來宣告常數, 它有兩個必要參數, 一個備用參數 :

bool define (string $name , mixed $value [, bool $case_insensitive = false] )

第一個參數是常數名稱, 習慣上通常使用全英文大寫名稱來表示常數 (不可用 $ 開頭), 第二參數是常數的值. 備用參數用來設定常數名稱是否分大小寫, 預設是有分大小寫 (false), 例如 :

define("PI", 3.14159); //預設有分大小寫
echo PI; //輸出 3.14159
echo pi; //輸出 pi (把 pi 當成字串)

如果將第三參數設為 true, 則不分大小寫, 例如 :

define("PI", 3.14159, true); //不分大小寫
echo PI; //輸出 3.14159
echo pi; //輸出 3.14159 

注意, PHP 的常數定義之後就一直使用直到網頁結束, 其值只能是數值或字串, 且一旦定義之後不可再更改.


六. 運算子 (Operator) :


1. 算術運算子 :   

算術運算子有下列 5 個 :


運算子 說明範例 
 + 加法運算, + 也用來表示正值, 例如 $a=+5; $c=$a+$b;
 -減法運算, - 也用來表示負值, 例如 $a=-5; $c=$a-$b;
 *乘法運算$c=$a*$b
 /除法運算$a=1/3;  //結果 0.3333333...
 %餘數運算$a=20%3;  //結果 2


注意, 若算術運算的兩個運算元不為數值型態, PHP 將依型別轉換規則自動轉成數值, 例如 5+TRUE 得 6 (TRUE 轉成 1), 而 5+FALSE 得 5 (FALSE 轉成 0).


2. 字串運算子 : 

PHP 的字串運算子 (小數點) 用來連接字串. 字串運算子前後運算元如果不是字串型別, 會自動轉成字串, 例如 :

echo "Hello"." "."World";  //輸出 "Hello World"


3. 遞增遞減運算子 : 

有前置遞增 ++ 與後置遞增兩種, 差別在於運算的時間先後, 前置遞增或遞減會先進行運算再傳回其值, 後置運算則先傳回值再進行運算 :


 運算子 說明 範例 
 ++$a 前置遞增 : 先把變數加 1, 再傳回變數值 echo ++$a; //顯示 2
 $a++ 後置遞減 : 先傳回變數值, 再把變數加 1 echo $++a; //顯示 1
 --$a 前置遞增 : 先把變數加 1, 再傳回變數值 echo --$a; //顯示 0
 $a-- 後置遞減 : 先傳回變數值, 再把變數加 1 echo $a--; //顯示 1


4. 比較運算子 : 

比較運算子的傳回值為布林值 true 或 false, 主要用在 if else 判斷中 :


 運算子  說明 範例
 == 等於 (值相等) if $a == $b {... }
 === 全等 (值與資料型態均相等) 傳回 TRUE if $a === $b {... }
 != 不等於 (值) 傳回 TRUE  if $a != $b {... }
 !=== 不相等  (值或資料型態任一個不相等)  if $a !=== $b {... }
 < 小於 if $a < $b {... }
 > 大於 if $a > $b {... }
 <= 小於等於 if $a <= $b {... }
 >= 大於等於 if $a >= $b {... }


5. 邏輯運算子 :

邏輯運算子的運算元為布林值, 其中 and 運算可用 && 代替, 而 or 運算也可以用 || 代替 :


運算子  說明 範例
 and, && 邏輯且運算, 兩者均為 True 才為 True if $a and $b {... }, if $a && $b {...}
 or, || 邏輯或運算, 兩者有一為 True 即為 True if $a or $b {...}, if $a || $b {...}
 xor 邏輯互斥或運算, 只有一個為 True 才為 True if $ xor $b {...}
 ! 邏輯反相運算, True 變 False, False 變 True if !$a {... }



6. 位元運算子 :

位元運算子會將整數運算元拆成二進位進行逐位元邏輯運算 :


運算子  說明 範例
 & 位元且運算, 兩者的位元均為 1 才為 1 $c=$a & $b
 | 位元或運算, 兩者的位元有一為 1 即為 1 $c=$a | $b
 ^ 位元互斥運算, 兩者的位元有一為 1 即為 1 $c=$a ^ $b
 ~ 位元反相運算, 位元 1 變成 0, 0 變成 1  $c=~$a
 << 位元左移運算 $c=$a << $b
 >>  位元右移運算 $c=$a >> $b


7. 指派運算子 :

包含單純指派 = 以及與算術, 字串運算子結合之複合指派運算子如下表 :


運算子 說明範例 
 =指派賦值 $a=123
 += 加法指派  $a+=$b; 相當於 $a=$a+$b;
 -=減法指派 $a-=$b; 相當於 $a=$a-$b;
 *=乘法指派 $a*=$b; 相當於 $a=$a*$b;
 /=除法指派 $a*/$b; 相當於 $a=$a/$b;
 %=餘數指派 $a%=$b; 相當於 $a=$a%$b;
 .=字串連接指派 $a.=$b; 相當於 $a=$a.$b;



六. 流程控制 : 

流程控制有分支與迴圈兩種, 分支即條件式判斷, 而迴圈為循環結構 :


1. 分支 (branch) : 

PHP 的條件式有 if elseif else 與 switch case 兩種 :


 結構語法範例 
 單一條件一結果  if (條件式) {
     敘述
     }
 if ($score < 60)
    echo "不及格";
 單一條件兩結果  if (條件式) {
     敘述1
     }
  else {
     敘述2
     }
 if ($score < 60) {echo "不及格";}
 else {echo "及格";}
 //只有一行時不須大括弧 :
 if ($score < 60) echo "不及格";
 else echo "及格";
 
 多重條件式  if (條件式1) {
     敘述1
     }
  elseif (條件式2) {
     敘述2
     }
  else {
     敘述3
     }
 if ($score >= 90) {echo "優";}
 elseif ($score < 90 && $score >= 80) {echo "甲";}
 elseif ($score < 80 && $score >= 70) {echo "乙";}
 elseif ($score < 70 && $score >= 60) {echo "丙";}
 else {echo "不及格";} 
 單一條件式多重結果  switch (條件式) {
      case 值1 :
              敘述1;
              break;
       case 值2 :
               敘述2;
               break;
       default :
               預設敘述
       }
 switch ($fruit) {  //條件變數為字串
    case "apple" : {echo "蘋果"; break;}
    case "watermelon" : {echo "西瓜"; break;}
    default : {echo "水果";}
    }
 switch ($state) {  //條件變數為數值
    case 0 : {echo "False"; break;}
    case 1 : {echo "True"; break;}
    default : {echo "Undefined";}
    }
    


注意, switch case 的條件變數可以是數值 (整數或浮點數均可) 或字串, 每一個 case 應該以 break 結束, 否則會一直往下執行到尾端的 default, 但 default 不用 break 結束. 每個 case 與 default 的內容即使是多行也不須用大括弧包起來. 各 case 的值不須一致, 可以有的是數值, 有的是字串, 例如 :

case 1.2 : {...break;}
case "ok" : {... break;}


2. 迴圈 : 

PHP 的迴圈有 for, while, do while, foreach 四種語法結構, 搭配 break, continue, 以及 exit 進行迴圈控制 :


語法結構範例 
 計數式迴圈
 for ([初始運算式]; [條件式]; [更新運算式]) {
      敘述
      }
 $sum=0;
 for ($i=1; $i <= 10; $i++) {
     $sum += $i;
      } 


 for ($i=1; ; $i++) {  //變化規則改到迴圈內部
     if ($i > 10) break;     
//大於 10 就跳出迴圈
     $sum += $i;
      }  

 $sum=0;
 $i=0;  
 for (; ;) { 
    if ($i > 10) break;    
//跳出無窮迴圈
    $sum += $i
     $i++;
     }   
 陣列式迴圈
 foreach ($array as $value) {
   敘述
   }

 foreach ($array as $key => $value) {
   敘述
   }
 $fruits=Array("蘋果", "西瓜", "葡萄");
 foreach ($fruits as $value) {
     echo "$value"
     }
 $fruits=Array("Apple" => "蘋果",
                       "watermelon" => "西瓜",
                       "grapes" => "葡萄");
 foreach ($fruits as $key => $value) {
     echo "$key : $value"
     } 
   
 條件式迴圈
 while (條件式) {
    敘述
    }
 $i=0;
 $sum=0;
 while ($i <= 10) {
        $sum += $i;
        $i++;
        }
   
 條件式迴圈
 do {
     敘述
     }
 while (條件式);
 $i=0;
 $sum=0;
 do {
      $sum += $i;
      $i++;
      }
  while ($i <= 10); 
 break 與 continue  $user=Array("Peter", "Tom", "", "Mary", "", "Kelly");
 for ($i=0; $i < count($user); $i++) {
     if ($user[$i] == "") {continue;}    //空字串就跳過
     echo "Name : $user[$i]
";
     }    
 exit for ($i=0; $i<10 br="" i="">     if ($i==5) {echo "程式中止執行";}
     echo $i."
";
     }  //輸出 0 到 4 後停止執行



七. 陣列 : 

PHP 的陣列為關聯式陣列 (associate array 或 ordered map), 可儲存異質性資料 (即元素型別可以不同), 其鍵可以是整數或字串, 這與 C 或 Java 等語言的向量陣列 (vector array) 不同, 向量陣列必須事先宣告大小以事先配置記憶體, 且每個元素型別必須相同 (同質), 只能使用整數鍵存取, 但存取效率較佳. 

PHP 關聯式陣列特性為 :
  • 陣列的大小不必事先宣告 (故 PHP 不會事先配置記憶體給陣列, 而是動態配置).
  • 每個元素的資料型別可以不同 (數值, 字串, 陣列, 物件), 例如 :
    $arr=Array(123, "ABC")
  • 可用整數或字串為鍵存取元素, 亦即 PHP 陣列的鍵只允許整數或字串, 而元素值則沒有限制, 任何資料型態均可.
  • 可以用中括號或大括號存取元素, 例如 $arr[0] 或 $arr{0}


1. 建立陣列 :

建立陣列的方法有兩種, 第一種方式為直接指定元素, 以中括號內的鍵 (key) 或索引來指定陣列元素的值, 索引 (鍵) 可以是整數或字串, 索引也可以不指定, 這時 PHP 會自動依序指定, 即將前一個整數索引加 1. 例如 :

$arr[0]=100;
$arr[1]=200;
$arr[]=300;   //索引自動指派 2
$arr['hana']="花"

第二種方式為呼叫 array() 內建函式並傳入以逗號隔開的 "鍵=>值" 對元素作為參數, 例如 :

$arr=array(0=>100, 1=>200, 2=>300, 'hana'=>'花');

若未指定鍵則自動以 0, 1, 2, 3 ... 指派索引, 例如下面陣列與上面相同 :

$arr=array(100, 200, 300, 'hana'=>'花');

存取陣列使用中括號內置索引, 例如 :

$arr=array(100, 200, 300, 'hana'=>'花');
echo $arr[0];  //輸出 100
echo $arr[1];  //輸出 200
echo $arr['hana'];   //輸出 '花'
print_r($arr);  //顯示陣列結構

顯示陣列結構可呼叫內建函數 print_r() 或 var_dump(), 不能用 echo, 它只能用來顯示陣列元素, 若用 echo 顯示整個陣列 $arr 只會輸出 "Array", 表示這是個陣列型態的變數而已. 上面的陣列結構輸出如下 :

Array ( [0] => 100 [1] => 200 [2] => 300 [hana] => 花 )

二維陣列具有兩個索引鍵, 可以直接指定元素值來建立, 例如 :

$arr[0][0]='00';
$arr[0][1]='01';
$arr[1][0]='10';
$arr[1][1]='11';
print_r($arr);

也可以呼叫 array(), 例如 :

$arr=array(array('00', '01'), array('10', '11'));
print_r($arr);

事實上二維陣列就是以一維陣列當元素, 上面的陣列與下面一樣 :

$arr1=array('00', '01');
$arr2=array('10', '11');
$arr=array($arr1, $arr2);
print_r($arr);

上面三種寫法都會輸出如下結果 :

Array ( [0] => Array ( [0] => 00 [1] => 01 ) [1] => Array ( [0] => 10 [1] => 11 ) )


2. 拜訪陣列 :

拜訪陣列可使用 for 迴圈, 適合用在索引為預設連續整數時, 例如 :

$arr=array(100, 200, 300, 'hana'=>'花');
for ($i=0; $i<count($arr); $i++) {
  echo $arr[$i];   //輸出 100200300
  }

上面範例含有字串索引, $arr['hana'] 並不是 $arr[3], 因此沒有輸出 $arr['hana']. 如果索引含有字串, 則必須用 foreach 迴圈來拜訪, 因位它可將陣列的鍵值用 as 分裂出來, 例如 :

$arr=array(100, 200, 300, 'hana'=>'花');
foreach ($arr as $key => $value) {
  echo "$key: $value ";  //輸出 0: 100 1: 200 2: 300 hana: 花 
  }
拜訪二維陣列需使用兩層迴圈, 例如 :

$arr1=array('春'=>'Spring', '夏'=>'Summer');
$arr2=array('秋'=>'Fall', '冬'=>'Winter');
$arr=array($arr1, $arr2);
for ($i=0; $i<count($arr); $i++) {
  foreach ($arr[$i] as $key => $value) {
    echo "$key: $value ";
    }
  }

此範例輸出如下 :

春: Spring 夏: Summer 秋: Fall 冬: Winter

3. 內建陣列函式 :

常用的內建陣列函式如下表 :


 函數  說明
 count($arr) 傳回陣列 $arr 之長度 (元素個數)
 sizeof($arr) 傳回陣列 $arr 之長度 (元素個數)
 list($var1, $var2, ...)=$arr 將陣列 $arr 的各元素依索引順序傳回 list 中指定的變數, 多出的變數值為 NULL
 var_dump($array) 輸出陣列元素之索引與值
 print_r($arr) 輸出陣列元素之索引與值
 is_array($array) 檢查變數是否為陣列, 是傳回 true, 否傳回 false


其中 count() 與 sizeof() 功能相同, 常用在拜訪陣列的迴圈中. 注意, 對於一維陣列而言, count() 與 sizeof() 傳回全部元素個數; 但對二維陣列而言, 傳回的是其列數而非全部元素個數.

var_dump() 與 print_r() 都會顯示陣列結構與內容, var_dump() 輸出資訊較多, 會顯示元素個數與資料型態, print_r() 則只顯示結構與元素內容而已, 例如 :

$arr=array(100, 200, 300, 'hana' => '花');
echo is_array($arr);
echo "<br>";
list($a, $b, $c, $d)=$arr;
echo $a, $b, $c, $d;
echo "<br>";
print_r($arr);
echo "<br>";
var_dump($arr);

此例輸出結果如下 :

1
100200300
Array ( [0] => 100 [1] => 200 [2] => 300 [hana] => 花 )
array(4) { [0]=> int(100) [1]=> int(200) [2]=> int(300) ["hana"]=> string(3) "花" }

此例中呼叫 list() 將陣列元素拆解到變數中, 但 $arr['hana'] 卻無法指派到 $d 變數, 可見 list() 函式僅對整數索引有效, 對字串索引無效. 

沒有留言:

張貼留言