PHP8 String 字符串

2023-08-14 15:22 更新

一個(gè)字符串 string 就是由一系列的字符組成,其中每個(gè)字符等同于一個(gè)字節(jié)。這意味著 PHP 只能支持 256 的字符集,因此不支持 Unicode 。詳見(jiàn)字符串類型詳解。

注意: 在 32 位版本中,string 最大可以達(dá)到 2GB(最多 2147483647 字節(jié))。

語(yǔ)法

一個(gè)字符串可以用 4 種方式表達(dá):

  • 單引號(hào)
  • 雙引號(hào)
  • heredoc 語(yǔ)法結(jié)構(gòu)
  • nowdoc 語(yǔ)法結(jié)構(gòu)

單引號(hào)

定義一個(gè)字符串的最簡(jiǎn)單的方法是用單引號(hào)把它包圍起來(lái)(字符 ')。

要表達(dá)一個(gè)單引號(hào)自身,需在它的前面加個(gè)反斜線(\)來(lái)轉(zhuǎn)義。要表達(dá)一個(gè)反斜線自身,則用兩個(gè)反斜線(\\)。其它任何方式的反斜線都會(huì)被當(dāng)成反斜線本身:也就是說(shuō)如果想使用其它轉(zhuǎn)義序列例如 \r 或者 \n,并不代表任何特殊含義,就單純是這兩個(gè)字符本身。

注意: 不像雙引號(hào)和 heredoc 語(yǔ)法結(jié)構(gòu),在單引號(hào)字符串中的變量和特殊字符的轉(zhuǎn)義序列將不會(huì)被替換。
<?php
echo 'this is a simple string';

// 可以錄入多行
echo 'You can also have embedded newlines in
strings this way as it is
okay to do';

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

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

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

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

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

雙引號(hào)

如果字符串是包圍在雙引號(hào)(")中, PHP 將對(duì)以下特殊的字符進(jìn)行解析:

轉(zhuǎn)義字符
序列含義
\n換行(ASCII 字符集中的 LF 或 0x0A (10))
\r回車(ASCII 字符集中的 CR 或 0x0D (13))
\t水平制表符(ASCII 字符集中的 HT 或 0x09 (9))
\v垂直制表符(ASCII 字符集中的 VT 或 0x0B (11))
\eEscape(ASCII 字符集中的 ESC 或 0x1B (27))
\f換頁(yè)(ASCII 字符集中的 FF 或 0x0C (12))
\\反斜線
\$美元標(biāo)記
\"雙引號(hào)
\[0-7]{1,3}符合該正則表達(dá)式序列的是一個(gè)以八進(jìn)制方式來(lái)表達(dá)的字符,which silently overflows to fit in a byte (e.g. "\400" === "\000")
\x[0-9A-Fa-f]{1,2}符合該正則表達(dá)式序列的是一個(gè)以十六進(jìn)制方式來(lái)表達(dá)的字符
\u{[0-9A-Fa-f]+}匹配正則表達(dá)式的字符序列是 unicode 碼位, 該碼位能作為 UTF-8 的表達(dá)方式輸出字符串

和單引號(hào)字符串一樣,轉(zhuǎn)義任何其它字符都會(huì)導(dǎo)致反斜線被顯示出來(lái)。

用雙引號(hào)定義的字符串最重要的特征是變量會(huì)被解析,詳見(jiàn)變量解析。

Heredoc 結(jié)構(gòu) ?

第三種表達(dá)字符串的方法是用 heredoc 句法結(jié)構(gòu):<<<。在該運(yùn)算符之后要提供一個(gè)標(biāo)識(shí)符,然后換行。接下來(lái)是字符串 string 本身,最后要用前面定義的標(biāo)識(shí)符作為結(jié)束標(biāo)志。

結(jié)束標(biāo)識(shí)符可以使用空格或制表符(tab)縮進(jìn),此時(shí)文檔字符串會(huì)刪除所有縮進(jìn)。 在 PHP 7.3.0 之前的版本中,結(jié)束時(shí)所引用的標(biāo)識(shí)符必須在該行的第一列。

而且,標(biāo)識(shí)符的命名也要像其它標(biāo)簽一樣遵守 PHP 的規(guī)則:只能包含字母、數(shù)字和下劃線,并且必須以字母和下劃線作為開(kāi)頭。

示例 #1 PHP 7.3.0 之后的基礎(chǔ) Heredoc 示例

<?php
// 無(wú)縮進(jìn)
echo <<<END
a
b
c
\n
END;
// 4 空格縮進(jìn)
echo <<<END
a
b
c
END;

以上示例在 PHP 7.3 中的輸出:

      a
     b
    c
  a
 b
c

如果結(jié)束標(biāo)識(shí)符的縮進(jìn)超過(guò)內(nèi)容的任何一行的縮進(jìn),則將拋出 ParseError 異常:

示例 #2 結(jié)束標(biāo)識(shí)符的縮進(jìn)不能超過(guò)正文的任何一行

<?php
echo <<<END
a
b
c
END;

以上示例在 PHP 7.3 中的輸出:

PHP Parse error:  Invalid body indentation level (expecting an indentation level of at least 3) in example.php on line 4

制表符也可以縮進(jìn)結(jié)束標(biāo)識(shí)符,但是,關(guān)于縮進(jìn)結(jié)束標(biāo)識(shí)符和內(nèi)容, 制表符和空格不能混合使用。在以上任何情況下, 將會(huì)拋出 ParseError 異常。 之所以包含這些空白限制,是因?yàn)榛旌现票矸涂崭駚?lái)縮進(jìn)不利于易讀性。

示例 #3 內(nèi)容(空白)和結(jié)束標(biāo)識(shí)符的不同縮進(jìn)

<?php
// 以下所有代碼都不起作用。
// 正文(空格)和結(jié)束標(biāo)記(制表符),不同的縮進(jìn)
{
echo <<<END
a
END;
}
// 在正文中混合空格和制表符
{
echo <<<END
a
END;
}
// 在結(jié)束標(biāo)記中混合空格和制表符
{
echo <<<END
a
END;
}

以上示例在 PHP 7.3 中的輸出:

PHP Parse error:  Invalid indentation - tabs and spaces cannot be mixed in example.php line 8

內(nèi)容字符串的結(jié)束標(biāo)識(shí)符后面不需要跟分號(hào)或者換行符。 例如,從 PHP 7.3.0 開(kāi)始允許以下代碼:

示例 #4 在結(jié)束標(biāo)識(shí)符后繼續(xù)表達(dá)式

<?php
$values = [<<<END
a
b
c
END, 'd e f'];
var_dump($values);

以上示例在 PHP 7.3 中的輸出:

array(2) {
  [0] =>
  string(11) "a
  b
    c"
  [1] =>
  string(5) "d e f"
}
警告

如果在某一行的開(kāi)頭找到了結(jié)束標(biāo)識(shí)符,那么不管它是否是另外一個(gè)單詞的一部分, 它都可能看作結(jié)束標(biāo)識(shí)符并引起 ParseError。

示例 #5 字符串內(nèi)容中的結(jié)束標(biāo)識(shí)符往往會(huì)導(dǎo)致 ParseError

<?php
$values = [<<<END
a
b
END ING
END, 'd e f'];

以上示例在 PHP 7.3 中的輸出:

PHP Parse error:  syntax error, unexpected identifier "ING", expecting "]" in example.php on line 6

為了避免這個(gè)問(wèn)題,遵循以下簡(jiǎn)單的規(guī)則較為安全: 不要選擇正文內(nèi)容中出現(xiàn)的詞作為結(jié)束標(biāo)識(shí)符。

警告

在 PHP 7.3.0 之前,請(qǐng)務(wù)必注意,帶有結(jié)束標(biāo)識(shí)符的行不能包含除 (;)外的任何其他字符。 這意味著標(biāo)識(shí)符不能縮進(jìn),分號(hào)的前后也不能有任何空白或制表符。更重要的是結(jié)束標(biāo)識(shí)符的前面必須是個(gè)被本地操作系統(tǒng)認(rèn)可的換行,比如在 UNIX 和 macOS 系統(tǒng)中是 \n,而結(jié)束定界符之后也必須緊跟一個(gè)換行。

如果不遵守該規(guī)則導(dǎo)致結(jié)束標(biāo)識(shí)不“干凈”,PHP 將認(rèn)為它不是結(jié)束標(biāo)識(shí)符而繼續(xù)尋找。如果在文件結(jié)束前也沒(méi)有找到一個(gè)正確的結(jié)束標(biāo)識(shí)符,PHP 將會(huì)在最后一行產(chǎn)生一個(gè)解析錯(cuò)誤。

示例 #6 PHP 7.3.0 之前的錯(cuò)誤示例

<?php
class foo {
public $bar = <<<EOT
bar
EOT;
}
// 不能縮進(jìn)標(biāo)識(shí)符
?>

示例 #7 即使在 PHP 7.3.0 之前也合法的示例

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

Heredocs 結(jié)構(gòu)不能用來(lái)初始化類的屬性。

Heredoc 結(jié)構(gòu)就象是沒(méi)有雙引號(hào)的 string,這就是說(shuō)在 heredoc 結(jié)構(gòu)中單引號(hào)不用被轉(zhuǎn)義,但是上文中列出的轉(zhuǎn)義序列還可以使用。變量將被替換,但在 heredoc 結(jié)構(gòu)中含有復(fù)雜的變量時(shí)要像 string 一樣格外小心。

示例 #8 Heredoc 結(jié)構(gòu)的字符串示例


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

/* 含有變量的更復(fù)雜示例 */
class foo
{
var $foo;
var $bar;

function __construct()
{
$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;
?>

以上示例會(huì)輸出:

My name is "MyName". I am printing some Foo.
Now, I am printing some Bar2.
This should print a capital 'A': A

也可以把 Heredoc 結(jié)構(gòu)用在函數(shù)參數(shù)中來(lái)傳遞數(shù)據(jù):

示例 #9 Heredoc 結(jié)構(gòu)在參數(shù)中的示例

<?php
var_dump(array(<<<EOD
foobar!
EOD
));
?>

可以用 Heredoc 結(jié)構(gòu)來(lái)初始化靜態(tài)變量和類的屬性和常量:

示例 #10 使用 Heredoc 結(jié)構(gòu)來(lái)初始化靜態(tài)值

<?php
// 靜態(tài)變量
function foo()
{
static $bar = <<<LABEL
Nothing in here...
LABEL;
}

// 類的常量、屬性
class foo
{
const BAR = <<<FOOBAR
Constant example
FOOBAR;

public $baz = <<<FOOBAR
Property example
FOOBAR;
}
?>

還可以在 Heredoc 結(jié)構(gòu)中用雙引號(hào)來(lái)聲明標(biāo)識(shí)符:

示例 #11 在 heredoc 結(jié)構(gòu)中使用雙引號(hào)

<?php
echo <<<"FOOBAR"
Hello World!
FOOBAR;
?>

Nowdoc 結(jié)構(gòu) ?

就象 heredoc 結(jié)構(gòu)類似于雙引號(hào)字符串,Nowdoc 結(jié)構(gòu)是類似于單引號(hào)字符串的。Nowdoc 結(jié)構(gòu)很象 heredoc 結(jié)構(gòu),但是 nowdoc 中不進(jìn)行解析操作。這種結(jié)構(gòu)很適合用于嵌入 PHP 代碼或其它大段文本而無(wú)需對(duì)其中的特殊字符進(jìn)行轉(zhuǎn)義。與 SGML 的 <![CDATA[ ]]> 結(jié)構(gòu)是用來(lái)聲明大段的不用解析的文本類似,nowdoc 結(jié)構(gòu)也有相同的特征。

一個(gè) nowdoc 結(jié)構(gòu)也用和 heredocs 結(jié)構(gòu)一樣的標(biāo)記 <<<, 但是跟在后面的標(biāo)識(shí)符要用單引號(hào)括起來(lái),即 <<<'EOT'。Heredoc 結(jié)構(gòu)的所有規(guī)則也同樣適用于 nowdoc 結(jié)構(gòu),尤其是結(jié)束標(biāo)識(shí)符的規(guī)則。

示例 #12 Nowdoc 結(jié)構(gòu)字符串示例

<?php
echo <<<'EOD'
Example of string spanning multiple lines
using nowdoc syntax. Backslashes are always treated literally,
e.g. \\ and \'.
EOD;

以上示例會(huì)輸出:

Example of string spanning multiple lines
using nowdoc syntax. Backslashes are always treated literally,
e.g. \\ and \'.

示例 #13 含變量引用的 Nowdoc 字符串示例


<?php

/* 含有變量的更復(fù)雜的示例 */
class foo
{
public $foo;
public $bar;

function __construct()
{
$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 not print a capital 'A': \x41
EOT;
?>

以上示例會(huì)輸出:

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

示例 #14 靜態(tài)數(shù)據(jù)的示例

<?php
class foo {
public $bar = <<<'EOT'
bar
EOT;
}
?>
注意:Nowdoc 結(jié)構(gòu)是在 PHP 5.3.0 中加入的。

變量解析 ?

當(dāng)字符串用雙引號(hào)或 heredoc 結(jié)構(gòu)定義時(shí),其中的變量將會(huì)被解析。

這里共有兩種語(yǔ)法規(guī)則:一種簡(jiǎn)單規(guī)則,一種復(fù)雜規(guī)則。簡(jiǎn)單的語(yǔ)法規(guī)則是最常用和最方便的,它可以用最少的代碼在一個(gè) string 中嵌入一個(gè)變量,一個(gè) array 的值,或一個(gè) object 的屬性。

復(fù)雜規(guī)則語(yǔ)法的顯著標(biāo)記是用花括號(hào)包圍的表達(dá)式。

簡(jiǎn)單語(yǔ)法

當(dāng) PHP 解析器遇到一個(gè)美元符號(hào)($)時(shí),它會(huì)和其它很多解析器一樣,去組合盡量多的標(biāo)識(shí)以形成一個(gè)合法的變量名??梢杂没ɡㄌ?hào)來(lái)明確變量名的界線。

<?php
$juice = "apple";

echo "He drank some $juice juice.".PHP_EOL;
// Invalid. "s" is a valid character for a variable name, but the variable is $juice.
echo "He drank some juice made of $juices.";
// Valid. Explicitly specify the end of the variable name by enclosing it in braces:
echo "He drank some juice made of ${juice}s.";
?>

以上示例會(huì)輸出:

He drank some apple juice.
He drank some juice made of .
He drank some juice made of apples.

類似的,一個(gè) array 索引或一個(gè) object 屬性也可被解析。數(shù)組索引要用方括號(hào)(])來(lái)表示索引結(jié)束的邊際,對(duì)象屬性則是和上述的變量規(guī)則相同。

示例 #15 簡(jiǎn)單語(yǔ)法示例


<?php
$juices = array("apple", "orange", "koolaid1" => "purple");

echo "He drank some $juices[0] juice.".PHP_EOL;
echo "He drank some $juices[1] juice.".PHP_EOL;
echo "He drank some $juices[koolaid1] juice.".PHP_EOL;

class people {
public $john = "John Smith";
public $jane = "Jane Smith";
public $robert = "Robert Paulsen";

public $smith = "Smith";
}

$people = new people();

echo "$people->john drank some $juices[0] juice.".PHP_EOL;
echo "$people->john then said hello to $people->jane.".PHP_EOL;
echo "$people->john's wife greeted $people->robert.".PHP_EOL;
echo "$people->robert greeted the two $people->smiths."; // Won't work
?>

以上示例會(huì)輸出:

He drank some apple juice.
He drank some orange juice.
He drank some purple juice.
John Smith drank some apple juice.
John Smith then said hello to Jane Smith.
John Smith's wife greeted Robert Paulsen.
Robert Paulsen greeted the two .

從 PHP 7.1.0 起,還支持負(fù)數(shù)字索引。

示例 #16 負(fù)數(shù)索引

<?php
$string = 'string';
echo "The character at index -2 is $string[-2].", PHP_EOL;
$string[-3] = 'o';
echo "Changing the character at index -3 to o gives $string.", PHP_EOL;
?>

以上示例會(huì)輸出:

The character at index -2 is n.
Changing the character at index -3 to o gives strong.

如果想要表達(dá)更復(fù)雜的結(jié)構(gòu),請(qǐng)用復(fù)雜語(yǔ)法。

復(fù)雜(花括號(hào))語(yǔ)法

復(fù)雜語(yǔ)法不是因?yàn)槠湔Z(yǔ)法復(fù)雜而得名,而是因?yàn)樗梢允褂脧?fù)雜的表達(dá)式。

任何具有 string 表達(dá)的標(biāo)量變量,數(shù)組單元或?qū)ο髮傩远伎墒褂么苏Z(yǔ)法。 表達(dá)式的書寫方式與在 string 以外的方式相同, 然后用花括號(hào) { 和 } 把它括起來(lái)即可。由于 { 無(wú)法被轉(zhuǎn)義,只有 $ 緊挨著 { 時(shí)才會(huì)被識(shí)別??梢杂?nbsp;{\$ 來(lái)表達(dá) {$。下面的示例可以更好的解釋:

<?php
// 顯示所有錯(cuò)誤
error_reporting(E_ALL);

$great = 'fantastic';

// 無(wú)效,輸出: This is { fantastic}
echo "This is { $great}";

// 有效,輸出: This is fantastic
echo "This is {$great}";

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

// 有效,只有通過(guò)花括號(hào)語(yǔ)法才能正確解析帶引號(hào)的鍵名
echo "This works: {$arr['key']}";

// 有效
echo "This works: {$arr[4][3]}";

// 這是錯(cuò)誤的表達(dá)式,因?yàn)榫拖?$foo[bar] 的格式在字符串以外也是錯(cuò)的一樣。
// 換句話說(shuō),只有在 PHP 能找到常量 foo 的前提下才會(huì)正常工作;這里會(huì)產(chǎn)生一個(gè)
// E_NOTICE (undefined constant) 級(jí)別的錯(cuò)誤。
echo "This is wrong: {$arr[foo][3]}";

// 有效,當(dāng)在字符串中使用多重?cái)?shù)組時(shí),一定要用括號(hào)將它括起來(lái)
echo "This works: {$arr['foo'][3]}";

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

echo "This works too: {$obj->values[3]->name}";

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

echo "This is the value of the var named by the return value of getName(): {${getName()}}";

echo "This is the value of the var named by the return value of \$object->getName(): {${$object->getName()}}";

// 無(wú)效,輸出: This is the return value of getName(): {getName()}
echo "This is the return value of getName(): {getName()}";

// 無(wú)效, 輸出: C:\folder\{fantastic}.txt
echo "C:\folder\{$great}.txt"
// 有效, 輸出: C:\folder\fantastic.txt
echo "C:\\folder\\{$great}.txt"
?>

也可以在字符串中用此語(yǔ)法通過(guò)變量來(lái)調(diào)用類的屬性。

<?php
class foo {
var $bar = 'I am bar.';
}

$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}\n";
echo "{$foo->{$baz[1]}}\n";
?>

以上示例會(huì)輸出:


I am bar.


I am bar.

注意:函數(shù)、方法、靜態(tài)類變量和類常量可使用 {$} ,在該字符串被定義的命名空間中將其值作為變量名來(lái)訪問(wèn)。只單一使用花括號(hào) ({}) 無(wú)法處理從函數(shù)或方法的返回值或者類常量以及類靜態(tài)變量的值。
<?php
// 顯示所有錯(cuò)誤
error_reporting(E_ALL);

class beers {
const softdrink = 'rootbeer';
public static $ale = 'ipa';
}

$rootbeer = 'A & W';
$ipa = 'Alexander Keith\'s';

// 有效,輸出: I'd like an A & W
echo "I'd like an {${beers::softdrink}}\n";

// 也有效,輸出: I'd like an Alexander Keith's
echo "I'd like an {${beers::$ale}}\n";
?>

存取和修改字符串中的字符

string 中的字符可以通過(guò)一個(gè)從 0 開(kāi)始的下標(biāo),用類似 array 結(jié)構(gòu)中的方括號(hào)包含對(duì)應(yīng)的數(shù)字來(lái)訪問(wèn)和修改,比如 $str[42]??梢园?nbsp;string 當(dāng)成字符組成的 array。函數(shù) substr() 和 substr_replace() 可用于操作多于一個(gè)字符的情況。

注意: 從 PHP 7.1.0 開(kāi)始,還支持 string 負(fù)偏移量。從 string 尾部到指定位置的偏移量。 以前,負(fù)偏移量讀取時(shí)(返回空 string)會(huì)發(fā)出 E_NOTICE, 寫入時(shí)(string 保持不變)會(huì)發(fā)出 E_WARNING。
注意: PHP 8.0.0 之前, 出于同樣的目的,可以使用大括號(hào)訪問(wèn) string,例如 $str{42}。 從 PHP 7.4.0 起,此大括號(hào)語(yǔ)法被棄用,自 PHP 8.0.0 開(kāi)始不再受支持。
警告
用超出字符串長(zhǎng)度的下標(biāo)寫入將會(huì)拉長(zhǎng)該字符串并以空格填充。非整數(shù)類型下標(biāo)會(huì)被轉(zhuǎn)換成整數(shù)。非法下標(biāo)類型會(huì)產(chǎn)生一個(gè) E_WARNING 級(jí)別錯(cuò)誤。 寫入時(shí)只用到了賦值字符串的第一個(gè)字符。 PHP 7.1.0 開(kāi)始,用空字符串賦值會(huì)導(dǎo)致 fatal 錯(cuò)誤;在之前賦給的值是 NULL 字符。
警告
PHP 的字符串在內(nèi)部是字節(jié)組成的數(shù)組。因此用花括號(hào)訪問(wèn)或修改字符串對(duì)多字節(jié)字符集很不安全。僅應(yīng)對(duì)單字節(jié)編碼例如 ISO-8859-1 的字符串進(jìn)行此類操作。
注意: 從 PHP 7.1.0 開(kāi)始,對(duì)空字符串應(yīng)用空索引運(yùn)算符會(huì)引發(fā)致命錯(cuò)誤。 以前是空字符串會(huì)被靜默轉(zhuǎn)為數(shù)組。

示例 #17 一些字符串示例

<?php
// 取得字符串的第一個(gè)字符
$str = 'This is a test.';
$first = $str[0];

// 取得字符串的第三個(gè)字符
$third = $str[2];

// 取得字符串的最后一個(gè)字符
$str = 'This is still a test.';
$last = $str[strlen($str)-1];

// 修改字符串的最后一個(gè)字符
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';

?>

字符串下標(biāo)必須為整數(shù)或可轉(zhuǎn)換為整數(shù)的字符串,否則會(huì)發(fā)出警告。之前類似 "foo" 的下標(biāo)會(huì)無(wú)聲地轉(zhuǎn)換成 0。

示例 #18 字符串無(wú)效下標(biāo)的例子

<?php
$str = 'abc';

var_dump($str['1']);
var_dump(isset($str['1']));

var_dump($str['1.0']);
var_dump(isset($str['1.0']));

var_dump($str['x']);
var_dump(isset($str['x']));

var_dump($str['1x']);
var_dump(isset($str['1x']));
?>

以上示例會(huì)輸出:

string(1) "b"
bool(true)

Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
string(1) "b"
bool(false)

Warning: Illegal string offset 'x' in /tmp/t.php on line 9
string(1) "a"
bool(false)
string(1) "b"
bool(false)
注意:用 [] 或 {} 訪問(wèn)任何其它類型(不包括數(shù)組或具有相應(yīng)接口的對(duì)象實(shí)現(xiàn))的變量只會(huì)無(wú)聲地返回 null。
注意:可以直接在字符串原型中用 [] 或 {} 訪問(wèn)字符。
注意:PHP 7.4 中棄用在字符串字面量中使用 {} 來(lái)訪問(wèn)字符。 PHP 8.0 已移除。

有用的函數(shù)和運(yùn)算符

字符串可以用 '.'(點(diǎn))運(yùn)算符連接起來(lái),注意 '+'(加號(hào))運(yùn)算符沒(méi)有這個(gè)功能。更多信息參考字符串運(yùn)算符。

對(duì)于 string 的操作有很多有用的函數(shù)。

可以參考字符串函數(shù)了解大部分函數(shù),高級(jí)的查找與替換功能可以參考 Perl 兼容正則表達(dá)式函數(shù)。

另外還有 URL 字符串函數(shù),也有加密/解密字符串的函數(shù)(Sodium 和 Hash)。

最后,可以參考字符類型函數(shù)。

轉(zhuǎn)換成字符串 ?

一個(gè)值可以通過(guò)在其前面加上 (string) 或用 strval() 函數(shù)來(lái)轉(zhuǎn)變成字符串。在一個(gè)需要字符串的表達(dá)式中,會(huì)自動(dòng)轉(zhuǎn)換為 string。這發(fā)生在當(dāng)使用 echo 或 print 函數(shù),或當(dāng)變量與 string 進(jìn)行比較的時(shí)候。類型和類型轉(zhuǎn)換可以更好的解釋下面的事情,也可參考函數(shù) settype()。

一個(gè)布爾值 bool 的 true 被轉(zhuǎn)換成 string 的 "1"。bool 的 false 被轉(zhuǎn)換成 ""(空字符串)。這種轉(zhuǎn)換可以在 bool 和 string 之間相互進(jìn)行。

一個(gè)整數(shù) int 或浮點(diǎn)數(shù) float 被轉(zhuǎn)換為數(shù)字的字面樣式的 string(包括 float 中的指數(shù)部分)。使用指數(shù)計(jì)數(shù)法的浮點(diǎn)數(shù)(4.1E+6)也可轉(zhuǎn)換。

注意:PHP 8.0.0 起,十進(jìn)制小數(shù)點(diǎn)字符都是一個(gè)句號(hào)(.)。 而在此之前的版本,在腳本的區(qū)域(category LC_NUMERIC) 中定義了十進(jìn)制小數(shù)點(diǎn)字符。參見(jiàn) setlocale()。

數(shù)組 array 總是轉(zhuǎn)換成字符串 "Array",因此,echo 和 print 無(wú)法顯示出該數(shù)組的內(nèi)容。要顯示某個(gè)單元,可以用 echo $arr['foo'] 這種結(jié)構(gòu)。要顯示整個(gè)數(shù)組內(nèi)容見(jiàn)下文。

必須使用魔術(shù)方法 __toString 才能將 object 轉(zhuǎn)換為 string。

資源 Resource 總會(huì)被轉(zhuǎn)變成 "Resource id #1" 這種結(jié)構(gòu)的字符串,其中的 1 是 PHP 在運(yùn)行時(shí)分配給該 resource 的資源數(shù)字。 While the exact structure of this string should not be relied on and is subject to change, it will always be unique for a given resource within the lifetime of a script being executed (ie a Web request or CLI process) and won't be reused. 要得到一個(gè) resource 的類型,可以用函數(shù) get_resource_type()。

null 總是被轉(zhuǎn)變成空字符串。

如上面所說(shuō)的,直接把 array,object 或 resource 轉(zhuǎn)換成 string 不會(huì)得到除了其類型之外的任何有用信息??梢允褂煤瘮?shù) print_r() 和 var_dump() 列出這些類型的內(nèi)容。

大部分的 PHP 值可以轉(zhuǎn)變成 string 來(lái)永久保存,這被稱作串行化,可以用函數(shù) serialize() 來(lái)實(shí)現(xiàn)。

字符串類型詳解 ?

PHP 中的 string 的實(shí)現(xiàn)方式是一個(gè)由字節(jié)組成的數(shù)組再加上一個(gè)整數(shù)指明緩沖區(qū)長(zhǎng)度。并無(wú)如何將字節(jié)轉(zhuǎn)換成字符的信息,由程序員來(lái)決定。字符串由什么值來(lái)組成并無(wú)限制;特別的,其值為 0(“NUL bytes”)的字節(jié)可以處于字符串任何位置(不過(guò)有幾個(gè)函數(shù),在本手冊(cè)中被稱為非“二進(jìn)制安全”的,也許會(huì)把 NUL 字節(jié)之后的數(shù)據(jù)全都忽略)。

字符串類型的此特性解釋了為什么 PHP 中沒(méi)有單獨(dú)的“byte”類型 - 已經(jīng)用字符串來(lái)代替了。返回非文本值的函數(shù) - 例如從網(wǎng)絡(luò)套接字讀取的任意數(shù)據(jù) - 仍會(huì)返回字符串。

由于 PHP 并不特別指明字符串的編碼,那字符串到底是怎樣編碼的呢?例如字符串 "á" 到底是等于 "\xE1"(ISO-8859-1),"\xC3\xA1"(UTF-8,C form),"\x61\xCC\x81"(UTF-8,D form)還是任何其它可能的表達(dá)呢?答案是字符串會(huì)被按照該腳本文件相同的編碼方式來(lái)編碼。因此如果一個(gè)腳本的編碼是 ISO-8859-1,則其中的字符串也會(huì)被編碼為 ISO-8859-1,以此類推。不過(guò)這并不適用于激活了 Zend Multibyte 時(shí);此時(shí)腳本可以是以任何方式編碼的(明確指定或被自動(dòng)檢測(cè))然后被轉(zhuǎn)換為某種內(nèi)部編碼,然后字符串將被用此方式編碼。注意腳本的編碼有一些約束(如果激活了 Zend Multibyte 則是其內(nèi)部編碼)- 這意味著此編碼應(yīng)該是 ASCII 的兼容超集,例如 UTF-8 或 ISO-8859-1。不過(guò)要注意,依賴狀態(tài)的編碼其中相同的字節(jié)值可以用于首字母和非首字母而轉(zhuǎn)換狀態(tài),這可能會(huì)造成問(wèn)題。

當(dāng)然了,要做到有用,操作文本的函數(shù)必須假定字符串是如何編碼的。不幸的是,PHP 關(guān)于此的函數(shù)有很多變種:

  • 某些函數(shù)假定字符串是以單字節(jié)編碼的,但并不需要將字節(jié)解釋為特定的字符。例如 substr(),strpos(),strlen() 和 strcmp()。理解這些函數(shù)的另一種方法是它們作用于內(nèi)存緩沖區(qū),即按照字節(jié)和字節(jié)下標(biāo)操作。
  • 某些函數(shù)被傳遞入了字符串的編碼方式,也可能會(huì)假定默認(rèn)無(wú)此信息。例如 htmlentities() 和 mbstring 擴(kuò)展中的大部分函數(shù)。
  • 其它函數(shù)使用了當(dāng)前區(qū)域(見(jiàn) setlocale()),但是逐字節(jié)操作。
  • 最后一些函數(shù)會(huì)假定字符串是使用某特定編碼的,通常是 UTF-8。intl 擴(kuò)展和 PCRE(上例中僅在使用了 u 修飾符時(shí))擴(kuò)展中的大部分函數(shù)都是這樣。

最后,要書寫能夠正確使用 Unicode 的程序依賴于很小心地避免那些可能會(huì)損壞數(shù)據(jù)的函數(shù)。要使用來(lái)自于 intl 和 mbstring 擴(kuò)展的函數(shù)。不過(guò)使用能處理 Unicode 編碼的函數(shù)只是個(gè)開(kāi)始。不管用何種語(yǔ)言提供的函數(shù),最基本的還是了解 Unicode 規(guī)格。例如一個(gè)程序如果假定只有大寫和小寫,那可是大錯(cuò)特錯(cuò)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)