介紹PHP中的資料型態(型別),包含字串(String)、陣列(Array)、物件(Object)、資源(Resource)、NULL,型別的判斷與轉型。

 

5. 字串(String)

5.1 語法

字串有四種使用的方式:

  1. 單引號
  2. 雙引號
  3. Heredoc
  4. Nowdoc

以下逐一進行介紹。

5.1-1 單引號

以兩個單引號包夾一段文字,表示字串內容,使用單引號的字串有一些特徵如下(與雙引號比較):

  1. 逸出字元(Escape characters)只有兩種。
  2. 逸出字元\\可省略寫作\,但不可為最後一個字元(不建議省略)。
  3. 不會對字串中的變數進行解析。

所謂逸出字元是為了某些特別的用途或能以此輸入打不出來的字,而定義的一種使用方式,在此的逸出字元以反斜線(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:

  1. 直接使用:"$var"
  2. 使用大括號一:"${var}"
  3. 使用大括號二:"{$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 轉型

要轉型為整數可利用以下方式

  1. 利用(string)的強制轉型。
  2. 利用strval()函式轉型。
  3. 利用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 轉型

要轉型為陣列可利用以下方式

  1. 利用(array)的強制轉型。
  2. 利用settype()傳入引數"array"。

將其他型別轉為陣列型別通常的行為是產生一個陣列,索引值0的位置為原型別內容,但NULLobject型別則例外,object型別轉換的規則如下:

  1. 只轉換變數成員函式成員不被轉換。
  2. public成員以[成員名稱]為陣列Key值。
  3. protected成員以[*成員名稱]為陣列Key值。
  4. 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 轉型

要轉型為物件可利用以下方式

  1. 利用(object)的強制轉型。
  2. 利用settype()傳入引數"object"。

將其他型別轉為物件型別通常的行為是產生一個stdClass物件,成員scalar為原型別內容,但NULLarray型別則例外,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()函式,注意這是將變數完全移除。

<?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。

延伸閱讀

上一篇 PHP教學 - 資料型態(Data Type) - 上

下一篇 PHP教學 - 變數(Variables)

文章標籤
創作者介紹

小殘的程式光廊

emn178 發表在 痞客邦 PIXNET 留言(0) 人氣()