简介
PHP中字符串的实现方式是一个由字节组成的数组再加上一个整数指明缓冲区长度。并无如何将字节转换成字符的信息,这是由程序员来决定的。字符串由什么值来组成并无限制;特别的,其值为 0 的字节可以处于字符串任何位置。
由于 PHP 并不特别指明字符串的编码,那字符串到底是怎样编码的呢?例如字符串 "á" 到底是等于 "\xE1"(ISO-8859-1),"\xC3\xA1"(UTF-8,C form),"\x61\xCC\x81"(UTF-8,D form)还是任何其它可能的表达呢?答案是字符串会被按照该脚本文件相同的编码方式来编码。
string最大可达2GB。
字符串的表示
php的字符串可以使用4种方式来表示,包括:
单引号/双引号/heredoc/nowdoc
这4种方式都支持将字符串写成多行,同时,字符串中的换行、空格都会原样保留在字符中,即保持源码中的格式。如果要消除换行,可以写成单行的形式,并使用字符串拼接运算符。
单引号使用简单,使用单引号时,转义字符只有两个,即\'和\\
如果字符串中包含了双引号,则使用单引号的方式将会十分简洁。
双引号则支持更多的转义字符,包括:
\n换行\r回车\t水平制表\v垂直制表\e退出(ESC)\f换页\\反斜线\$美元符\"双引号
此外,转义字符还支持八进制表示法、十六进制表示法和UTF-8表示法:
\[0-7]{1,3}
\x[0-9A-Fa-f]{1,2}
\u{[0-9A-Fa-f]+}
同样,双引号表示的字符串中,单引号不用进行转义。
双引号表示的字符串还有另一个重要的特点,就是会对字符串的中变量进行解析:
"Hi, $str."
语法分析器一旦碰到$符号,就会获取$符号的后面直到下一个不是英文字母、阿拉伯数字或下划线的字符之间的字符串,将其当成变量名称,若程序中没有这个变量,发出警告的同时会自动忽略(而不是原样输出)。
如果要输出$符号,则必须使用转义字符\$
heredoc语法
语法格式:
<<<str
字符串内容
str
注意,上面的str是一个自定义的标识符(开始标签处的str可以添加双引号,但结束标签不能),用于辅助标志字符串的开始和结束。此外,<<<str之后必须是一个换行符。
指定字符串结束的标识符必须是另起一行并且从第一列开始书写。这行除了后面可能有一个分号(;)外,绝对不能包含其它字符。这意味着标识符不能缩进,分号的前后也不能有任何空白或制表符。更重要的是结束标识符的前面必须是个被本地操作系统认可的换行,比如在 UNIX 和 Mac OS X 系统中是 \n,而结束定界符(可能其后有个分号)之后也必须紧跟一个换行。
heredoc语法与双引号表示法一样会对字符串中的变量进行解析,也可以使用多种转换字符。
注意,Heredoc 包含变量解析时,不能用来初始化类的属性。
不同于双引号语法,在heredox中,双引号不需要转义:
$a = <<<"xx"
abc\'\"
xx;
echo $a; // abc\'\"
nowdoc语法
语法格式:
<<<'str'
字符串内容
str
nowdoc语法与heredoc语法类似,特点是起始标识符必须由单引号包围(结束标志符不能带单引号)。而且nowdoc语法不会对字符串中的变量进行解析。
<?php
$name = "pish";
echo <<<'str1'
My name is $name.<br>
str1;
?>
不同于单引号语法,在nowdoc中,单引号和反斜线都不需要转义:
$b = <<<'xx'
abc\'\\
xx;
echo $b; // abc\'\\
字符串中的变量解析
最简单的方式是直接写变量名,例如:
$name = 'Ann';
$str = "hello $name!";
这种方式必须让变量名的末尾有一个不能用于变量命名的字符,比如上例中的"!",当然,除非是字符串已经结束。
如果变量名后跟的是一个字母或数字,那么变量就不会得到正确的解析,因为语法分析器一旦碰到$符号,就会获取$符号的后面直到下一个不是英文字母、阿拉伯数字或下划线的字符之间的字符串,将其当成变量名称,若程序中没有这个变量,则会自动忽略。
一个例外是数组元素,数组元素使用]标识了变量的结束,所以在]之后可以有其他字母或数字。
如果要更好的控制变量名或者使用一个复杂的表达式,则可以使用{}来辅助标识。
注意:
1.$和{必须紧挨在一起,比如:${或{$,否则花括号就会被解析为字符串中的一个普通字符。
2.必须有}符号,否则出错。
3.如果$符号是挨着变量名的,则它们之间不能有空格。
4.解析数组元素时,只有通过花括号语法才能正确解析带引号的键名
$str = "hello ${name}";
$str = "hello ${ name }";
$str = "hello {$name }";
$str = "hello {$ name }"; // 出错
$a = array(1,2,3);
$b = array('a'=>1, 'b'=>2, 'c'=>3);
echo "$a[0]"; // 正常
echo "${b['a']}"; // 不能省略花括号,否则出错
只使用一层花括号时,无法处理函数或方法的返回值或者类常量以及类静态变量。正确的做法是使用两层花括号:
{${getName()}} // 函数
{${$object->getName()}} // 方法
{${beers::softdrink}} // 类常量
{${beers::$ale}} // 类变量
注意,字符串中的“解析”为变量解析,所以函数、方法、类的常量或变量,都应该是字符串类型的变量名,这样才可以使用“变量解析”特性
function getName() {
return "a";
}
class beers
{
public const softdrink = 'b';
public static $ale = 'c';
public function getName() {return 'd';}
}
$object = new beers();
$a = 1;
$b = 2;
$c = 3;
$d = 4;
echo "{${getName()}}"; // 函数
echo "{${$object->getName()}}"; // 方法
echo "{${beers::softdrink}}"; // 类常量
echo "{${beers::$ale}}"; // 类变量
// 1423
下面的例子演示了字符串中的可变变量:
$name = 'Ann';
$Ann = 'Jeck';
echo "hello {${$name}}"; // hello Jeck
echo "hello ${$name}"; // hello Jeck
class foo {
var $bar = 'I am bar.';
}
$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}\n"; // I am bar.
echo "{$foo->{$baz[1]}}\n"; // I am bar.
以数组形式访问字符串
一个字符串可以当成一个可读写的数组进行访问,这时,数组的键固定为0、1、2...
可以使用方括号或花括号来访问字符串中的元素:
$str = "abcdefg";
$str[0] = "2";
$str{1} = 3;
echo var_dump($str); // string(7) "23cdefg"
注意,用超出字符串长度的下标写入将会拉长该字符串并以空格填充。非整数类型下标会被转换成整数。非法下标类型会产生一个 E_NOTICE 级别错误。用负数下标写入字符串时会产生一个 E_NOTICE 级别错误,用负数下标读取字符串时返回空字符串。写入时只用到了赋值字符串的第一个字符。用空字符串赋值则赋给的值是 NULL 字符。
PHP 的字符串在内部是字节组成的数组。因此用下标方式访问或修改字符串对多字节字符集很不安全。仅应对单字节编码例如 ISO-8859-1 的字符串进行此类操作。
通过字符串变量访问其它变量、函数等
在php中,变量名、函数名、类名、接口名等标识符,都可以通过一个字符串变量来间接访问
class MyClass
{
public const PI = 3.14;
}
function sayHello() {
return "hello\n";
}
$a = "world";
$sa = "a";
$sf = "sayHello";
$sc = "MyClass";
echo $$sa."\n"; // world
echo $sf(); // hello
echo $sc::PI; // 3.14
例子中,$var解释出来的字符串可以直接当成变量名、类名、函数名使用。
运算符
字符串支持以下这些运算符:
. .=
该运算符用于连接两个字符串:
$str1 = "hello " . "world";
$str1 .= "!";
echo $str1; // hello world!
字符串函数
strlen(str)
返回字符串的长度
$str1 = "abcdefg";
$str2 = "大家好!";
echo strlen($str1); // 7
echo strlen($str2); // 10