字串

string 是一系列字元。在 PHP 中,字元和位元組一樣,也就是說,一共有 256 種不同字元的可能性。這也暗示 PHP 對 Unicode 沒有本地支援。請參閱函數 utf8_encode()utf8_decode() 以瞭解有關 Unicode 支援。

注: 一個字串變得非常巨大也沒有問題,PHP 沒有給字串的大小強加實現範圍,所以完全沒有理由擔心長字串。

語法

字串可以用三種字面上的方法定義。

單引號

指定一個簡單字串的最簡單的方法是用單引號(字元 ')括起來。

要表示一個單引號,需要用反斜線(\)轉義,和很多其它語系一樣。若果在單引號之前或字串結尾需要出現一個反斜線,需要用兩個反斜線表示。注意若果試圖轉義任何其它字元,反斜線本身也會被顯示出來!所以通常不需要轉義反斜線本身。

注: 在 PHP 3 中,此情況下將發出一個 E_NOTICE 級的警示。

注: 和其他兩種語法不同,單引號字串中出現的變量和轉義序列不會被變量的值替代。

<?php
echo 'this is a simple string';

echo 
'You can also have embedded newlines in
strings this way as it is
okay to do'
;

// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I\'ll be back"';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\\*.*?';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?';

// Outputs: This will not expand: \n a newline
echo 'This will not expand: \n a newline';

// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either';
?>

雙引號

若果用雙引號(")括起字串,PHP 懂得更多特殊字元的轉義序列:

表格 11-1. 轉義字元

序列含義
\n換行(LF 或 ASCII 字元 0x0A(10))
\r換行(CR 或 ASCII 字元 0x0D(13))
\t水平製表符(HT 或 ASCII 字元 0x09(9))
\\反斜線
\$美元符號
\"雙引號
\[0-7]{1,3} 此正則表達式序列符合一個用八進位符號表示的字元
\x[0-9A-Fa-f]{1,2} 此正則表達式序列符合一個用十六進位符號表示的字元

此外,若果試圖轉義任何其它字元,反斜線本身也會被顯示出來!

雙引號字串最重要的一點是其中的變量名會被變量值替代。細節參見字串解析

定界符

另一種給字串定界的方法使用定界符語法(「<<<」)。應該在 <<< 之後提供一個標識符,然後是字串,然後是同樣的標識符結束字串。

結束標識符必須從行的第一列開始。同樣,標識符也必須遵循 PHP 中其它任何標籤的命名規則:只能包括字母數字下劃線,而且必須以下劃線或非數字字元開始。

警示

很重要的一點必須指出,結束標識符所在的行不能包括任何其它字元,可能除了一個分號(;)之外。這尤其意味著該標識符不能被縮進,而且在分號之前和之後都不能有任何空格或製表符。同樣重要的是要意識到在結束標識符之前的第一個字元必須是你的動作系統中定義的換行符。例如在 Macintosh 系統中是 \r

若果破壞了這條規則使得結束標識符不「乾淨」,則它不會被視為結束標識符,PHP 將繼續尋找下去。若果在這種情況下找不到合適的結束標識符,將會導致一個在腳本最後一行出現的語法錯誤。

不能用定界符語法起始化類成員。用其它字串語法替代。

例子 11-3. 非法的例子

<?php
class foo {
    public 
$bar = <<<EOT
bar
EOT;
}
?>

定界符文字表現的就和雙引號字串一樣,只是沒有雙引號。這意味著在定界符文字中不需要轉義引號,不過仍然可以用以上列出來的轉義代碼。變量會被展開,但當在定界符文字中表達複雜變量時和字串一樣同樣也要注意。

例子 11-4. 定界符字串例子

<?php
$str 
= <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    var 
$foo;
    var 
$bar;

    function 
foo()
    {
        
$this->foo 'Foo';
        
$this->bar = array('Bar1''Bar2''Bar3');
    }
}

$foo = new foo();
$name 'MyName';

echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some 
{$foo->bar[1]}.
This should print a capital 'A': 
\x41
EOT;
?>

注: 定界符支援是 PHP 4 中加入的。

變量解析

當用雙引號或是定界符指定字串時,其中的變量會被解析。

有兩種語法,一種簡單的和一種複雜的。簡單語法最通用和方便,它提供瞭解析變量,陣列值,或是物件屬性的方法。

複雜語法是 PHP 4 引進的,可以用花括號括起一個表達式。

簡單語法

若果遇到美元符號($),解析器會盡可能多地取得後面的字元以組成一個合法的變量名。若果想明示指定名字的結束,用花括號把變量名括起來。

<?php
$beer 
'Heineken';
echo 
"$beer's taste is great"// works, "'" is an invalid character for varnames
echo "He drank some $beers";   // won't work, 's' is a valid character for varnames
echo "He drank some ${beer}s"// works
echo "He drank some {$beer}s"// works
?>

同樣也可以解析陣列索引或是物件屬性。對於陣列索引,右方括號(])標誌著索引的結束。物件屬性則和簡單變量適用同樣的規則,儘管對於物件屬性沒有像變量那樣的小技巧。

<?php
// These examples are specific to using arrays inside of strings.
// When outside of a string, always quote your array string keys
// and do not use {braces} when outside of strings either.

// Let's show all errors
error_reporting(E_ALL);

$fruits = array('strawberry' => 'red''banana' => 'yellow');
// Works but note that this works differently outside string-quotes
echo "A banana is $fruits[banana].";
// Works
echo "A banana is {$fruits['banana']}.";

// Works but PHP looks for a constant named banana first
// as described below.
echo "A banana is {$fruits[banana]}.";

// Won't work, use braces.  This results in a parse error.
echo "A banana is $fruits['banana'].";

// Works
echo "A banana is " $fruits['banana'] . ".";

// Works

echo "This square is $square->width meters broad.";
// Won't work. For a solution, see the complex syntax.
echo "This square is $square->width00 centimeters broad.";
?>

對於任何更複雜的情況,應該使用複雜語法。

複雜(花括號)語法

不是因為語法複雜而稱其為複雜,而是因為用此方法可以包括複雜的表達式。

事實上,用此語法可以在字串中包括任何在名字空間的值。僅僅用和在字串之外同樣的方法寫一個表達式,然後用 { 和 } 把它包括進來。因為不能轉義「{」,此語法僅在 $ 緊跟在 { 後面時被識別(用「{\$」或是「\{$」來得到一個字面上的「{$」)。用一些例子可以更清晰:

<?php
// Let's show all errors
error_reporting(E_ALL);

$great 'fantastic';

// 不行,輸出為:This is { fantastic}
echo "This is { $great}";

// 可以,輸出為:This is fantastic
echo "This is {$great}";
echo 
"This is ${great}";

// Works
echo "This square is {$square->width}00 centimeters broad.";

// Works
echo "This works: {$arr[4][3]}";
// This is wrong for the same reason as $foo[bar] is wrong
// outside a string.  In otherwords, it will still work but
// because PHP first looks for a constant named foo, it will
// throw an error of level E_NOTICE (undefined constant).
echo "This is wrong: {$arr[foo][3]}";
// Works.  When using multi-dimensional arrays, always use
// braces around arrays when inside of strings
echo "This works: {$arr['foo'][3]}";

// Works.
echo "This works: " $arr['foo'][3];

echo 
"You can even write {$obj->values[3]->name}";

echo 
"This is the value of the var named $name: {${$name}}";
?>

訪問和修改字串中的字元

字串中的字元可以通過在字串之後用花括號指定所要字元從零開始的偏移量來訪問和修改。

注: 為了向下相容,仍然可以用方括號。不過此語法自 PHP 4 起已過時。

例子 11-5. 一些字串例子

<?php
// Get the first character of a string
$str 'This is a test.';
$first $str{0};
// Get the third character of a string
$third $str{2};

// Get the last character of a string.
$str 'This is still a test.';
$last $str{strlen($str)-1};

// Modify the last character of a string
$str 'Look at the sea';
$str{strlen($str)-1} = 'e';

?>

實用函數及運算符

字串可以用「.」(點)運算符連線。注意這裡不能用「+」(加)運算符。更多訊息參見字串運算符

有很多實用函數來改變字串。

普通函數見字串函數一節,進階搜尋和置換見正則表達式函數(兩種風格:PerlPOSIX 增加)。

還有 URL 字串函數,以及加密/解密字串的函數(mcryptmhash)。

最後,若果還是找不到想要的函數,參見字元類型函數

字串轉換

可以用 (string) 旗標或是 strval() 函數將一個值轉換為字串。當某表達式需要字串時,字串的轉換會在表達式範圍內自動完成。例如當使用 echo() 或是 print() 函數時,或是將一個變量值與一個字串進行比較的時候。閱讀手冊中有關類型類型戲法中的部分有助於更清楚一些。參見 settype()

布林值 TRUE 將被轉換為字串 "1",而值 FALSE 將被表示為 ""(即空字串)。這樣就可以隨意地在布林值和字串之間進行比較。

整數或浮點數數值在轉換成字串時,字串由表示這些數值的數字字元組成(浮點數還包括有指數部分)。

陣列將被轉換成字串 "Array",因此無法通過 echo() 或是 print() 函數來輸出陣列的內容。請參考下文以取得更多提示。

物件將被轉換成字串 "Object"。若果因為除錯需要,需要將對象的成員變量列印出來,請閱讀下文。若果希望得到該物件所依附的類的名稱,請使用函數 get_class()。自 PHP 5 起,若果合適可以用 __toString() 方法。

資源類型總是以 "Resource id #1" 的格式被轉換成字串,其中 1 是 PHP 在運行時給資源特殊的唯一標識。若果希望取得資源的類型,請使用函數 get_resource_type()

NULL 將被轉換成空字串。

正如以上所示,將陣列、物件或是資源列印出來,並不能提供任何關於這些值本身的有用的訊息。請參閱函數 print_r()var_dump(),對於除錯來說,這些是更好的列印值的方法。

可以將 PHP 的值轉換為字串以永久地儲存它們。這種方法被稱為序列化,可以用函數 serialize() 來完成該動作。若果在安裝 PHP 時建立了 WDDX 支援,還可以將 PHP 的值序列化為 XML 結構。

字串轉換為數值

當一個字串被當作數字來求值時,根據以下規則來決定結果的類型和值。

若果內含「.」,「e」或「E」其中任何一個字元的話,字串被當作 float 來求值。否則就被當作整數。

該值由字串最前面的部分決定。若果字串以合法的數字資料開始,就用該數字作為其值,否則其值為 0(零)。合法數字資料由可選的正負號開始,後面跟著一個或多個數字(可選地內含十進位分數),後面跟著可選的指數。指數是一個「e」或是「E」後面跟著一個或多個數字。

<?php
$foo 
"10.5";                // $foo is float (11.5)
$foo "-1.3e3";              // $foo is float (-1299)
$foo "bob-1.3e3";           // $foo is integer (1)
$foo "bob3";                // $foo is integer (1)
$foo "10 Small Pigs";       // $foo is integer (11)
$foo "10.2 Little Piggies"// $foo is float (14.2)
$foo "10.0 pigs " 1;          // $foo is float (11)
$foo "10.0 pigs " 1.0;        // $foo is float (11)
?>

此轉換的更多訊息見 Unix 手冊中關於 strtod(3) 的部分。

若果想測試本節中的任何例子,可以複製和貼上這些例子並且加上下面這一行自己看看會發生什麼:

<?php
echo "\$foo==$foo; type is " gettype ($foo) . "<br />\n";
?>

不要指望在將一個字元轉換成整型時能夠得到該字元的編碼(可能也會在 C 中這麼做)。若果希望在字元編碼和字元之間轉換,請使用 ord()chr() 函數。