PHP教學 - 資料型態(Data Type) - 下
介紹PHP中的資料型態(型別),包含字串(String)、陣列(Array)、物件(Object)、資源(Resource)、NULL,型別的判斷與轉型。
5. 字串(String)
5.1 語法
字串有四種使用的方式:
單引號
雙引號
Heredoc
Nowdoc
雙引號
Heredoc
Nowdoc
以下逐一進行介紹。
5.1-1 單引號
以兩個單引號包夾一段文字,表示字串內容,使用單引號的字串有一些特徵如下(與雙引號比較):
逸出字元(Escape characters)只有兩種。
逸出字元\\可省略寫作\,但不可為最後一個字元(不建議省略)。
不會對字串中的變數進行解析。
逸出字元\\可省略寫作\,但不可為最後一個字元(不建議省略)。
不會對字串中的變數進行解析。
所
謂逸出字元是為了某些特別的用途或能以此輸入打不出來的字,而定義的一種使用方式,在此的逸出字元以反斜線(backslash)開頭。例如,我們使用單
引號做包夾,但字串中如果出現單引號,將會誤判為字串結束單引號,所以使用\'來表示字串中的單引號。使用單引號的字串可用的逸出字元如下:
符號 | 說明 |
---|---|
\' | 單引號字元。 |
\\ | 反斜線字元。 |
一些使用範例如下:
<?php echo '基本用法'; echo '也可以 斷行'; echo 'You\'re a good man.'; // You're a good man. echo 'C:\\PHP'; // C:\PHP echo 'C:\PHP'; // C:\PHP // 不能在最後省略,\'會被解析為字元而缺少結尾單引號 //echo 'C:\PHP\'; // Parse error echo 'First line \n second line'; // First line \n second line echo 'text is $text'; // text is $text ?>
5.1-2 雙引號
以兩個雙引號包夾一段文字,表示字串內容,最主要的重點是,變數會在雙引號中被解析。
雙引號的逸出字元如下:
符號 | 說明 |
---|---|
\n | 換行字元(LF or 0x0A)。 |
\r | 歸位字元(CR or 0x0D)。 |
\t | 水平Tab字元(HT or 0x09)。 |
\v | 垂直tab字元(VT or 0x0B, PHP 5.2.5之後加入)。 |
\f | 跳頁字元(CR or 0x0C, PHP 5.2.5之後加入)。 |
\\ | 反斜線字元。 |
\$ | 錢號字元。 |
\" | 雙引號字元。 |
\[0-7]{1,3} | 以八進位法表示字元。 |
\x[0-9A-Fa-f]{1,2} | 以十六進位法表示字元。 |
一些使用範例如下:
<?php echo "\"You're a good man.\" she said."; // "You're a good man." she said. echo "C:\\PHP"; // C:\PHP echo "First line\nsecond line\x0Athird line"; // output: // First line // second line // third line $text = "hello"; echo "text is $text"; // text is hello echo "text is \$text"; // text is $text ?>
5.1-3 Heredoc
Heredoc使用<<<符號開始,後面接著一個自訂的標籤,最後以自訂的標籤作結束。
<?php $text="hello"; // 標籤之後不能有任何字元 $here=<<<EOT \t<a href="http://tw.yahoo.com">Yahoo</a><br/>\n text is $text<br/> EOT; EOT; // 標籤之前與分號之後不能有任何字元 echo $here; ?>
結果:
Yahoo text is hello EOT;
Heredoc與雙引號性質相似,除了Heredoc的雙引號視為一般字元不需使用逸出字元。
5.1-4 Nowdoc
在PHP5.3.0之後新增Nowdoc用法,Nowdoc使用<<<符號開始,後面接著一個使用單引號包夾的自訂標籤,最後以自訂的標籤作結束。
<?php $text = "hello"; // Nowdoc $now=<<<'EOT' C:\PHP\ You're a good man.\n text is $text EOT; echo $now; // C:\PHP\ You're a good man.\n text is $text // Heredoc $here=<<<"EOT" text is $text\n EOT; echo $here; // text is hello ?>
Nowdoc無法使用逸出字元,也不會解析變數,也就是純文字的內容。另外PHP5.3.0之後,相對於Nowdoc的單引號,Heredoc同時新增了使用雙引號包夾的用法。
5.2 變數解析
字串中可放入變數直接進行解析,在字串中使用變數的寫法有三種,假設有一變數$var:
直接使用:"$var"
使用大括號一:"${var}"
使用大括號二:"{$var}"
使用大括號一:"${var}"
使用大括號二:"{$var}"
某些情況下直接使用可能會不如預期,如下範例:
<?php $beer = 'Heineken'; echo "$beer's taste is great"; // 結果正確, 變數名稱不能使用單引號, 所以變數名稱解析為$beer echo "He drank some $beers"; // 結果不正確, 代入成變數$beers echo "He drank some ${beer}s"; // 結果正確 echo "He drank some {$beer}s"; // 結果正確 ?>
所以建議使用大括號的方式為佳,使用陣列或物件的變數的時候也常會有問題:
<?php $teletubbies = array('dindin' => '紫色', 'lala' => '黃色'); echo "拉拉是$teletubbies[lala]."; // 結果正確 echo "拉拉是{$teletubbies[lala]}."; // 結果正確, 因為目前沒有lala的常數, lala視為字串 const lala = '黃色'; echo "拉拉是{$teletubbies[lala]}."; // 結果不正確, lala常數值為'黃色', 轉成$teletubbies['黃色'], 無此元素 // parse error. //echo "拉拉是$teletubbies['lala']."; echo "拉拉是" . $teletubbies['lala'] . "."; // 結果正確 echo "拉拉是{$teletubbies['lala']}."; // 結果正確 $obj = new stdClass; $obj->height = 169; echo "$obj->height cm"; // 結果正確 echo "$obj->height00 mm"; // 結果不正確, 沒有 $obj->height00 此成員 echo "{$obj->height}00 mm"; // 結果正確 ?>
5.3 字串的操作
5.3-1 字元的存取修改
字串可簡單視為字元的陣列,可以用陣列的索引方式取得或修改某個字元,但並不能真的完全當作陣列使用。用法範例如下:
<?php $str = "I lose"; echo $str[4]; // s $str[4] = 'v'; echo $str; // I love var_dump($str[7]); // string(0) "", 超出陣列範圍 $str[7] = 'u'; // 中間自動補空白 echo $str; // I love u $str[-1] = 'x'; echo $str; // I love u, 負索引不會改變內容 ?>
5.3-2 字串的連接
PHP中,字串使用點(.)來作為連接運算子,而不是使用加號(+),如果使用加號的話,會自動將字串轉型為數字做運算。
<?php $hello = "Hello"; $str = $hello . " world."; echo $str; // Hello world. echo $hello + "world"; // 0 echo 30 + "00mm"; // 30, 參照轉型為整數和浮點數的部份就能理解 ?>
5.4 轉型
要轉型為整數可利用以下方式
利用(string)的強制轉型。
利用strval()函式轉型。
利用settype()傳入引數"string"。
利用strval()函式轉型。
利用settype()傳入引數"string"。
<?php var_dump((string) false); // string(0) "", 注意false為空字串 var_dump((string) true); // string(1) "1" var_dump((string) 178); // string(3) "178" var_dump((string) 169.99); // string(6) "169.99" var_dump((string) array()); // string(5) "Array" var_dump((string) array(55, 66)); // string(5) "Array" // var_dump((string) new stdClass); // PHP4: Object, PHP5: Catchable fatal error..., 發生錯誤 class MyObj { function __toString() { return "Hello world"; } } $obj = new MyObj; echo $obj; // PHP4: Object, PHP5: Hello world $fp = fopen("res.txt","w+"); var_dump((string) $fp); // string(14) "Resource id #3" fclose($fp); var_dump((string) NULL); // string(0) "" ?>
在PHP5之後的物件必須要實作__toString()的函式才能轉為字串,否則會出錯。
5.5 常見問題
5.5-1 常數誤用
在PHP中,變數使用錢號做開頭,而常數則無錢號,也因此造成許多情況下,未知的字詞就被視為常數處理,但若又無此常數,就會視為字串使用(如5.2中出現的情況)。
<?php $text = Hello; // 無Hello常數, 視為字串 echo $text; // Hello const world = "word"; $text = world; echo $text; // word $user = "emn178"; echo "Hello " . user; // Hello user, 有時少打錢號造成結果錯誤, 但解析又不會出錯 ?>
5.5-2 字串比較
如果直接拿兩個字串來比較的話,程式的邏輯上預設是逐字以字母順序來作比較,例如b大於a和ab大於aab(比對到第二個字元b>a),但在PHP中,他會先判斷兩者是否為數字內容(is_numeric為true),如果是的話就轉成數字比較:
<?php var_dump('1.22' > '01.23'); // bool(false), 兩者皆為數字, 轉為數字比較 var_dump('1.22.10' > '01.23.10'); // bool(true), 不為數字, 以字母比較, 第一個字元1 > 0 var_dump((float)'1.22.10' > (float)'01.23.10'); // bool(false) ?>
5.5-3 空字串修改
5.3-1中提到,以陣列方式去修改超出長度的字元時,會自動填入空白至該位置,但是當變數為空字串時為例外情況,他會被轉為陣列。
<?php $str = ""; $str[10] = "a"; var_dump($str); // array(1) { [10]=> string(1) "a" } ?>
6. 陣列(Array)
PHP中的陣列是有順序性的Map資料結構,所以他不只可以作為一般的陣列使用外,搭配相關函式還可以將他作為各種資料結構使用,例如:Stack, Queue, Hashtable...等
6.1 語法
在PHP中,使用array()來建立陣列,括號中使用Key => Value的鍵與值或Value來建立陣列元素,以逗號隔開元素,其中Key可為整數或字串:
array( key => value , value , ... )
一些範例如下:
<?php var_dump(array(178, 169.99, "30cm", array(9527))); // array(4) { [0]=> int(178) [1]=> float(169.99) [2]=> string(4) "30cm" [3]=> array(1) { [0]=> int(9527) } } // 可放入各種型別 var_dump(array('dindin'=>'紫色', 'lala'=>'黃色', 'teletubbies')); // array(3) { ["dindin"]=> string(4) "紫色" ["lala"]=> string(4) "黃色" [0]=> string(11) "teletubbies" } // 無指定Key值, 自動指派下一個數字索引 var_dump(array(3=>44, 66, 3=>55)); // array(2) { [3]=> int(55) [4]=> int(66) } // 重複Key, 由最後的覆蓋前面 ?>
陣列中的元素也可以是陣列,而成為多維陣列的應用。另外,print_r()函式與var_dump()類似,也可將變數內容顯示出來,但較為簡潔,以下部分改使用print_r()來呈現。
6.2 陣列存取
我們使用中括號([])加上Key來表示陣列中的元素,例如:$array['Key'],以此方式可以取得或修改陣列元素的內容,要清除陣列元素則用unset()函式。以下為存取陣列的相關範例:
<?php $ar = array(); $ar[] = 55; // 自動指派索引, $ar[0] $ar[] = 66; $ar[5] = 178; $ar[] = '30cm'; // $ar[6] $ar['dindin'] = "紫色"; print_r($ar); // Array ( [0] => 55 [1] => 66 [5] => 178 [6] => 30cm [dindin] => 紫色 ) $ar[1] = null; // null無法移除原素 unset($ar[6]); // 移除$ar[6]的元素 $ar[] = "169.99cm"; // $ar[7], 注意不是$ar[6] $ar[2] = 66; // 注意$ar[2]的順序在$ar[7]之後 print_r($ar); // Array ( [0] => 55 [1] => [5] => 178 [dindin] => 紫色 [7] => 169.99cm [2] => 66 ) $ar2[] = 169.99; // 未宣告變數$ar2, 自動轉為陣列 $ar2['lala'] = "黃色"; print_r($ar2); // Array ( [0] => 169.99 [lala] => 黃色 ) $ar3 = array('dindin' => array('id'=>9527, 'color'=>'紫色'), 'lala' => array('id'=>5566, 'color'=>'黃色')); echo $ar3['lala']['color']; // 黃色 $user = "dindin"; echo $ar3[$user]['id']; // 9527, Key也可使用變數 ?>
6.3 轉型
要轉型為陣列可利用以下方式
利用(array)的強制轉型。
利用settype()傳入引數"array"。
利用settype()傳入引數"array"。
將其他型別轉為陣列型別通常的行為是產生一個陣列,索引值0的位置為原型別內容,但NULL和object型別則例外,object型別轉換的規則如下:
只轉換變數成員,函式成員不被轉換。
public成員以[成員名稱]為陣列Key值。
protected成員以[*成員名稱]為陣列Key值。
private成員以[\0類別名稱\0成員名稱]為陣列Key值。
public成員以[成員名稱]為陣列Key值。
protected成員以[*成員名稱]為陣列Key值。
private成員以[\0類別名稱\0成員名稱]為陣列Key值。
<?php var_dump((array) true); // array(1) { [0]=> bool(true) } var_dump((array) 178); // array(1) { [0]=> int(178) } var_dump((array) 169.99); // array(1) { [0]=> float(169.99) } var_dump((array) "30cm"); // array(1) { [0]=> string(4) "30cm" } var_dump((array) NULL); // array(0) { }, 轉為空陣列, 而不是array(1) {[0] => NULL} // 物件變數成員會轉換成陣列索引值 class X { private $A = 1; // 將轉成 "\0X\0A" protected $B = 2; // 將轉成 "*B" public $C = 3; // 將轉成 "C" } class Y extends X { private $A = 4; // 將轉成 "\0Y\0A" protected $B = 5; // 將轉成 "*B", 蓋過父類別之$B public $C = 6; // 將轉成 "C", 蓋過父類別之$C var $XA = 7; // 將轉成 "XA" public function D() {} } $ar = (array) new Y(); var_dump($ar); // array(5) { ["YA"]=> int(4) ["*B"]=> int(5) ["C"]=> int(6) ["XA"]=> int(7) ["XA"]=> int(1) }, 看到兩個"XA", 但其實一個是"\0X\0A" var_dump($ar['YA']); // NULL var_dump($ar["\0Y\0A"]); // int(4) , 要上加\0財能正確取得 $fp = fopen("res.txt","w+"); var_dump((array) $fp); // array(1) { [0]=> resource(3) of type (stream) } fclose($fp); ?>
7. 物件(Object)
7.1 語法
物件使用new關鍵字來建立,物件一般由類別(Class)來定義內容,也可以使用基本的物件類別stdClass,使用範例如下:
<?php class A { public $M = 10; function F() { echo "Hello"; } } $a = new A(); // 或者簡寫為 $a = new A; echo $a->M; // 10 $a->F(); // Hello print_r($a); // A Object ( [M] => 10 ) $obj = new stdClass; print_r($obj); // stdClass Object ( ) $obj->x = 1; $obj->y = 2; print_r($obj); // stdClass Object ( [x] => 1 [y] => 2 ) ?>
7.2 物件存取
如7.1範例所示,物件使用->符號來叫用或存取成員。要注意
的地方是,如果將物件指派給其他變數,他是以傳址(Pass by reference)的方式指派,而不是傳值(Pass by
value)的方式複製一份,如果要進行複製,則可使用clone關鍵字,但是物件下的物件並不會遞迴複製。
<?php $obj = new stdClass; $obj->x = 1; $obj->y = 2; $obj->o = new stdClass; $obj->o->z = 3; $obj2 = $obj; $obj2->x = 100; echo $obj->x; // 100, $obj和$obj2為相同的物件 $obj3 = clone $obj; /* 這裡相當於 $obj3 = new stdClass; $obj3->x = $obj->x; $obj3->y = $obj->y; $obj3->o = $obj->o; */ $obj3->y = 200; echo $obj->y; // 2 $obj3->o->z = 300; echo $obj->o->z; // 300, 物件下的物件並沒有進行複製 ?>
7.3 轉型
要轉型為物件可利用以下方式
利用(object)的強制轉型。
利用settype()傳入引數"object"。
利用settype()傳入引數"object"。
將其他型別轉為物件型別通常的行為是產生一個stdClass物件,成員scalar為原型別內容,但NULL和array型別則例外,array型別會將陣列中的Key=>Value轉成物件成員:
<?php var_dump((object) false); // object(stdClass)#1 (1) { ["scalar"]=> bool(false) } var_dump((object) 178); // object(stdClass)#1 (1) { ["scalar"]=> int(178) } var_dump((object) 169.99); // object(stdClass)#1 (1) { ["scalar"]=> float(169.99) } var_dump((object) "30cm"); // object(stdClass)#1 (1) { ["scalar"]=> string(4) "30cm" } $obj = (object) array(55, "dindin"=>"紫色"); var_dump($obj); // object(stdClass)#1 (2) { [0]=> int(55) ["dindin"]=> string(4) "紫色" } echo $obj->dindin; // 紫色 //echo $obj->0; // parse error, 你無法取得名稱為數字的成員 $fp = fopen("res.txt","w+"); var_dump((object) $fp); // object(stdClass)#1 (1) { ["scalar"]=> resource(3) of type (stream) } fclose($fp); var_dump((object) NULL); // object(stdClass)#1 (0) { }, 為空物件, 而不是object(stdClass)#1 (1) { ["scalar"]=> NULL } ?>
8. 資源(Resource)
資源是特別的型別,為來自外部的資源參考,例如檔案串流等。由於轉型為資源並不具意義,故無法轉型為資源型別。資源的用法依據所使用的類別而定,故需各別參考該資源相關文件。
9. 空值(NULL)
9.1 語法
空值的值只有NULL一種內容,不分大小寫。
<?php $a = NuLl; var_dump($a == nUlL); // bool(true) ?>
9.2 轉型
轉型為空值並沒有特別的意義,但仍可利用以下方式
1. 利用(unset)的強制轉型。
2. 利用settype()傳入引數"null"轉型。(為PHP 4.2.0之後新增)
3. 利用unset()函式,注意這是將變數完全移除。
2. 利用settype()傳入引數"null"轉型。(為PHP 4.2.0之後新增)
3. 利用unset()函式,注意這是將變數完全移除。
<?php $ar = array(55, 66, 77, 88); settype($ar[0], "null"); unset($ar[1]); // $ar[1]將完全移除 var_dump((unset) $ar[2]); // NULL var_dump($ar); // array(3) { [0]=> NULL [2]=> int(77) [3]=> int(88) } ?>
10. 虛擬型別
這部份的型別在文件中使用到,並非實際的型別。
10.1 混合(Mixed)
混合型別在文件表示可以是多種的型別,但不一定是所有型別。例如str_replace()函式在文件中紀錄如下:
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
回傳為mixed的型別只有string或array兩種。
10.2 數字(Number)
數字型別表示可以是整數型別或浮點數型別。
10.3 回呼(Callback)
Callback型別表示某個函式的名稱,實際上傳入的型別是字串,不過在文件中對此用途特別稱為Callback。
留言
張貼留言