• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • String 字符串

    一个字符串string就是由一系列的字符组成,其中每个字符等同于一个字节。这意味着 PHP 只能支持 256 的字符集,因此不支持 Unicode 。详见字符串类型详解。

    Note:string最大可以达到 2GB。

    语法

    一个字符串可以用 4 种方式表达:

    • 单引号
    • 双引号
    • heredoc 语法结构
    • nowdoc 语法结构(自 PHP 5.3.0 起)

    单引号

    定义一个字符串的最简单的方法是用单引号把它包围起来(字符')。

    要表达一个单引号自身,需在它的前面加个反斜线()来转义。要表达一个反斜线自身,则用两个反斜线()。其它任何方式的反斜线都会被当成反斜线本身:也就是说如果想使用其它转义序列例如r或者n,并不代表任何特殊含义,就单纯是这两个字符本身。

    Note:不像双引号和heredoc语法结构,在单引号字符串中的变量和特殊字符的转义序列将不会被替换。

    <?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';
    ?>
    

    双引号

    如果字符串是包围在双引号(")中, PHP 将对一些特殊的字符进行解析:

    转义字符
    序列含义
    n换行(ASCII 字符集中的 LF 或 0x0A(10))
    r回车(ASCII 字符集中的 CR 或 0x0D(13))
    t水平制表符(ASCII 字符集中的 HT 或 0x09(9))
    v垂直制表符(ASCII 字符集中的 VT 或 0x0B(11))(自 PHP 5.2.5 起)
    eEscape(ASCII 字符集中的 ESC 或 0x1B(27))(自 PHP 5.4.0 起)
    f换页(ASCII 字符集中的 FF 或 0x0C(12))(自 PHP 5.2.5 起)
    反斜线
    $美元标记
    "双引号
    [0-7]{1,3}符合该正则表达式序列的是一个以八进制方式来表达的字符
    x[0-9A-Fa-f]{1,2}符合该正则表达式序列的是一个以十六进制方式来表达的字符

    和单引号字符串一样,转义任何其它字符都会导致反斜线被显示出来。PHP 5.1.1 以前,{$var}中的反斜线还不会被显示出来。

    用双引号定义的字符串最重要的特征是变量会被解析,详见变量解析。

    Heredoc 结构

    第三种表达字符串的方法是用 heredoc 句法结构:<<<。在该运算符之后要提供一个标识符,然后换行。接下来是字符串string本身,最后要用前面定义的标识符作为结束标志。

    结束时所引用的标识符必须在该行的第一列,而且,标识符的命名也要像其它标签一样遵守 PHP 的规则:只能包含字母、数字和下划线,并且必须以字母和下划线作为开头。

    Warning

    要注意的是结束标识符这行除了可能有一个分号(;)外,绝对不能包含其它字符。这意味着标识符不能缩进,分号的前后也不能有任何空白或制表符。更重要的是结束标识符的前面必须是个被本地操作系统认可的换行,比如在 UNIX 和 Mac OS X 系统中是n,而结束定界符(可能其后有个分号)之后也必须紧跟一个换行。

    如果不遵守该规则导致结束标识不“干净”,PHP 将认为它不是结束标识符而继续寻找。如果在文件结束前也没有找到一个正确的结束标识符,PHP 将会在最后一行产生一个解析错误。

    Heredocs 结构不能用来初始化类的属性。自 PHP 5.3 起,此限制仅对 heredoc 包含变量时有效。

    Example #1 非法的示例

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

    Heredoc 结构就象是没有使用双引号的双引号字符串,这就是说在 heredoc 结构中单引号不用被转义,但是上文中列出的转义序列还可以使用。变量将被替换,但在 heredoc 结构中含有复杂的变量时要格外小心。

    Example #2 Heredoc 结构的字符串示例

    <?php
    $str = <<<EOD
    Example of string
    spanning multiple lines
    using heredoc syntax.
    EOD;
    /* 含有变量的更复杂示例 */
    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;
    ?>
    

    以上例程会输出:

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

    也可以把 Heredoc 结构用在函数参数中来传递数据:

    Example #3 Heredoc 结构在参数中的示例

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

    在 PHP 5.3.0 以后,也可以用 Heredoc 结构来初始化静态变量和类的属性和常量:

    Example #4 使用 Heredoc 结构来初始化静态值

    <?php
    // 静态变量
    function foo()
    {
        static $bar = <<<LABEL
    Nothing in here...
    LABEL;
    }
    // 类的常量、属性
    class foo
    {
        const BAR = <<<FOOBAR
    Constant example
    FOOBAR;
        public $baz = <<<FOOBAR
    Property example
    FOOBAR;
    }
    ?>
    

    自 PHP 5.3.0 起还可以在 Heredoc 结构中用双引号来声明标识符:

    Example #5 在 heredoc 结构中使用双引号

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

    Nowdoc 结构

    就象 heredoc 结构类似于双引号字符串,Nowdoc 结构是类似于单引号字符串的。Nowdoc 结构很象 heredoc 结构,但是 nowdoc 中不进行解析操作。这种结构很适合用于嵌入 PHP 代码或其它大段文本而无需对其中的特殊字符进行转义。与 SGML 的<![CDATA[]]>结构是用来声明大段的不用解析的文本类似,nowdoc 结构也有相同的特征。

    一个 nowdoc 结构也用和 heredocs 结构一样的标记<<<,但是跟在后面的标识符要用单引号括起来,即<<<'EOT'。Heredoc 结构的所有规则也同样适用于 nowdoc 结构,尤其是结束标识符的规则。

    Example #6 Nowdoc 结构字符串示例

    <?php
    $str = <<<'EOD'
    Example of string
    spanning multiple lines
    using nowdoc syntax.
    EOD;
    /* 含有变量的更复杂的示例 */
    class foo
    {
        public $foo;
        public $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 not print a capital 'A': \x41
    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

    Note:

    不象 heredoc 结构,nowdoc 结构可以用在任意的静态数据环境中,最典型的示例是用来初始化类的属性或常量:

    Example #7 静态数据的示例

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

    Note:

    Nowdoc 结构是在 PHP 5.3.0 中加入的。

    变量解析

    当字符串用双引号或 heredoc 结构定义时,其中的变量将会被解析。

    这里共有两种语法规则:一种简单规则,一种复杂规则。简单的语法规则是最常用和最方便的,它可以用最少的代码在一个string中嵌入一个变量,一个array的值,或一个object的属性。

    复杂规则语法的显著标记是用花括号包围的表达式。

    简单语法

    当 PHP 解析器遇到一个美元符号($)时,它会和其它很多解析器一样,去组合尽量多的标识以形成一个合法的变量名。可以用花括号来明确变量名的界线。

    <?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.";
    ?>
    

    以上例程会输出:

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

    类似的,一个array索引或一个object属性也可被解析。数组索引要用方括号(])来表示索引结束的边际,对象属性则是和上述的变量规则相同。

    Example #8 简单语法示例

    <?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 juice made of $juice[0]s.".PHP_EOL; // Won't work
    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
    ?>
    

    以上例程会输出:

    He drank some apple juice.
    He drank some orange juice.
    He drank some juice made of s.
    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 .
    

    如果想要表达更复杂的结构,请用复杂语法。

    复杂(花括号)语法

    复杂语法不是因为其语法复杂而得名,而是因为它可以使用复杂的表达式。

    任何具有string表达的标量变量,数组单元或对象属性都可使用此语法。只需简单地像在string以外的地方那样写出表达式,然后用花括号{}把它括起来即可。由于{无法被转义,只有$紧挨着{时才会被识别。可以用{$来表达{$。下面的示例可以更好的解释:

    <?php
    // 显示所有错误
    error_reporting(E_ALL);
    $great = 'fantastic';
    // 无效,输出: This is { fantastic}
    echo "This is { $great}";
    // 有效,输出: This is fantastic
    echo "This is {$great}";
    echo "This is ${great}";
    // 有效
    echo "This square is {$square->width}00 centimeters broad."; 
    // 有效,只有通过花括号语法才能正确解析带引号的键名
    echo "This works: {$arr['key']}";
    // 有效
    echo "This works: {$arr[4][3]}";
    // 这是错误的表达式,因为就象 $foo[bar] 的格式在字符串以外也是错的一样。
    // 换句话说,只有在 PHP 能找到常量 foo 的前提下才会正常工作;这里会产生一个
    // E_NOTICE (undefined constant) 级别的错误。
    echo "This is wrong: {$arr[foo][3]}"; 
    // 有效,当在字符串中使用多重数组时,一定要用括号将它括起来
    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()}}";
    // 无效,输出: This is the return value of getName(): {getName()}
    echo "This is the return value of getName(): {getName()}";
    ?>
    

    也可以在字符串中用此语法通过变量来调用类的属性。

    <?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";
    ?>
    

    以上例程会输出:


    I am bar.
    I am bar.
    Note:

    函数、方法、静态类变量和类常量只有在 PHP 5 以后才可在{$}中使用。然而,只有在该字符串被定义的命名空间中才可以将其值作为变量名来访问。只单一使用花括号({})无法处理从函数或方法的返回值或者类常量以及类静态变量的值。

    <?php
    // 显示所有错误
    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中的字符可以通过一个从 0 开始的下标,用类似array结构中的方括号包含对应的数字来访问和修改,比如$str[42]。可以把string当成字符组成的array。函数substr()和substr_replace()可用于操作多于一个字符的情况。

    Note:string也可用花括号访问,比如$str{42}

    Warning

    用超出字符串长度的下标写入将会拉长该字符串并以空格填充。非整数类型下标会被转换成整数。非法下标类型会产生一个E_NOTICE级别错误。用负数下标写入字符串时会产生一个E_NOTICE级别错误,用负数下标读取字符串时返回空字符串。写入时只用到了赋值字符串的第一个字符。用空字符串赋值则赋给的值是 NULL 字符。

    Warning

    PHP 的字符串在内部是字节组成的数组。因此用花括号访问或修改字符串对多字节字符集很不安全。仅应对单字节编码例如 ISO-8859-1 的字符串进行此类操作。

    Example #9 一些字符串示例

    <?php
    // 取得字符串的第一个字符
    $str = 'This is a test.';
    $first = $str[0];
    // 取得字符串的第三个字符
    $third = $str[2];
    // 取得字符串的最后一个字符
    $str = 'This is still a test.';
    $last = $str[strlen($str)-1]; 
    // 修改字符串的最后一个字符
    $str = 'Look at the sea';
    $str[strlen($str)-1] = 'e';
    ?>
    

    自 PHP 5.4 起字符串下标必须为整数或可转换为整数的字符串,否则会发出警告。之前类似"foo"的下标会无声地转换成0

    Example #10 PHP 5.3 和 PHP 5.4 的区别

    <?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']));
    ?>
    

    以上例程在PHP 5.3中的输出:

    string(1) "b"
    bool(true)
    string(1) "b"
    bool(true)
    string(1) "a"
    bool(true)
    string(1) "b"
    bool(true)
    

    以上例程在PHP 5.4中的输出:

    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)
    

    Note:

    []{}访问任何其它类型(不包括数组或具有相应接口的对象实现)的变量只会无声地返回NULL

    Note:

    PHP 5.5 增加了直接在字符串原型中用[]{}访问字符的支持。

    有用的函数和运算符

    字符串可以用'.'(点)运算符连接起来,注意'+'(加号)运算符没有这个功能。更多信息参考字符串运算符。

    对于string的操作有很多有用的函数。

    可以参考字符串函数了解大部分函数,高级的查找与替换功能可以参考正则表达式函数或Perl 兼容正则表达式函数。

    另外还有URL 字符串函数,也有加密/解密字符串的函数(mcrypt和mhash)。

    最后,可以参考字符类型函数。

    转换成字符串

    一个值可以通过在其前面加上(string)或用strval()函数来转变成字符串。在一个需要字符串的表达式中,会自动转换为string。比如在使用函数echo或print时,或在一个变量和一个string进行比较时,就会发生这种转换。类型和类型转换可以更好的解释下面的事情,也可参考函数settype()。

    一个布尔值boolean的TRUE被转换成string的"1"。Boolean的FALSE被转换成""(空字符串)。这种转换可以在boolean和string之间相互进行。

    一个整数integer或浮点数float被转换为数字的字面样式的string(包括float中的指数部分)。使用指数计数法的浮点数(4.1E+6)也可转换。

    Note:

    在脚本的区域(category LC_NUMERIC)中定义了十进制小数点字符。参见setlocale()。

    数组array总是转换成字符串"Array",因此,echo和print无法显示出该数组的内容。要显示某个单元,可以用echo $arr['foo']这种结构。要显示整个数组内容见下文。

    在 PHP 4 中对象object总是被转换成字符串"Object",如果为了调试原因需要打印出对象的值,请继续阅读下文。为了得到对象的类的名称,可以用get_class()函数。自 PHP 5 起,适当时可以用__toString方法。

    资源resource总会被转变成"Resource id #1"这种结构的字符串,其中的1是 PHP 在运行时分配给该resource的唯一值。不要依赖此结构,可能会有变更。要得到一个resource的类型,可以用函数get_resource_type()。

    NULL总是被转变成空字符串。

    如上面所说的,直接把array,object或resource转换成string不会得到除了其类型之外的任何有用信息。可以使用函数print_r()和var_dump()列出这些类型的内容。

    大部分的 PHP 值可以转变成string来永久保存,这被称作串行化,可以用函数serialize()来实现。如果 PHP 引擎设定支持WDDX,PHP 值也可被串行化为格式良好的 XML 文本。

    字符串转换为数值

    当一个字符串被当作一个数值来取值,其结果和类型如下:

    如果该字符串没有包含'.','e'或'E'并且其数字值在整型的范围之内(由PHP_INT_MAX所定义),该字符串将被当成integer来取值。其它所有情况下都被作为float来取值。

    该字符串的开始部分决定了它的值。如果该字符串以合法的数值开始,则使用该数值。否则其值为 0(零)。合法数值由可选的正负号,后面跟着一个或多个数字(可能有小数点),再跟着可选的指数部分。指数部分由'e'或'E'后面跟着一个或多个数字构成。

    <?php
    $foo = 1 + "10.5";                // $foo is float (11.5)
    $foo = 1 + "-1.3e3";              // $foo is float (-1299)
    $foo = 1 + "bob-1.3e3";           // $foo is integer (1)
    $foo = 1 + "bob3";                // $foo is integer (1)
    $foo = 1 + "10 Small Pigs";       // $foo is integer (11)
    $foo = 4 + "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()实现 ASCII 码和字符间的转换。

    字符串类型详解

    PHP 中的string的实现方式是一个由字节组成的数组再加上一个整数指明缓冲区长度。并无如何将字节转换成字符的信息,由程序员来决定。字符串由什么值来组成并无限制;特别的,其值为0(“NUL bytes”)的字节可以处于字符串任何位置(不过有几个函数,在本手册中被称为非“二进制安全”的,也许会把 NUL 字节之后的数据全都忽略)。

    字符串类型的此特性解释了为什么 PHP 中没有单独的“byte”类型- 已经用字符串来代替了。返回非文本值的函数- 例如从网络套接字读取的任意数据- 仍会返回字符串。

    由于 PHP 并不特别指明字符串的编码,那字符串到底是怎样编码的呢?例如字符串"á"到底是等于"xE1"(ISO-8859-1),"xC3xA1"(UTF-8,C form),"x61xCCx81"(UTF-8,D form)还是任何其它可能的表达呢?答案是字符串会被按照该脚本文件相同的编码方式来编码。因此如果一个脚本的编码是 ISO-8859-1,则其中的字符串也会被编码为 ISO-8859-1,以此类推。不过这并不适用于激活了 Zend Multibyte 时;此时脚本可以是以任何方式编码的(明确指定或被自动检测)然后被转换为某种内部编码,然后字符串将被用此方式编码。注意脚本的编码有一些约束(如果激活了 Zend Multibyte 则是其内部编码)-这意味着此编码应该是 ASCII 的兼容超集,例如 UTF-8 或 ISO-8859-1。不过要注意,依赖状态的编码其中相同的字节值可以用于首字母和非首字母而转换状态,这可能会造成问题。

    当然了,要做到有用,操作文本的函数必须假定字符串是如何编码的。不幸的是,PHP 关于此的函数有很多变种:

    • 某些函数假定字符串是以单字节编码的,但并不需要将字节解释为特定的字符。例如substr(),strpos(),strlen()和strcmp()。理解这些函数的另一种方法是它们作用于内存缓冲区,即按照字节和字节下标操作。
    • 某些函数被传递入了字符串的编码方式,也可能会假定默认无此信息。例如htmlentities()和mbstring扩展中的大部分函数。
    • 其它函数使用了当前区域(见setlocale()),但是逐字节操作。例如strcasecmp(),strtoupper()和ucfirst()。这意味着这些函数只能用于单字节编码,而且编码要与区域匹配。例如strtoupper("á")在区域设定正确并且á是单字节编码时会返回"Á"。如果是用 UTF-8 编码则不会返回正确结果,其结果根据当前区域有可能返回损坏的值。
    • 最后一些函数会假定字符串是使用某特定编码的,通常是 UTF-8。intl扩展和PCRE(上例中仅在使用了u修饰符时)扩展中的大部分函数都是这样。尽管这是由于其特殊用途,utf8_decode()会假定 UTF-8 编码而utf8_encode()会假定 ISO-8859-1 编码。

    最后,要书写能够正确使用 Unicode 的程序依赖于很小心地避免那些可能会损坏数据的函数。要使用来自于intl和mbstring扩展的函数。不过使用能处理 Unicode 编码的函数只是个开始。不管用何种语言提供的函数,最基本的还是了解 Unicode 规格。例如一个程序如果假定只有大写和小写,那可是大错特错。

    I've been a PHP programmer for a decade, and I've always been using the "single-quoted literal" and "period-concatenation" method of string creation. But I wanted to answer the performance question once and for all, using sufficient numbers of iterations and a modern PHP version. For my test, I used:
    php -v
    PHP 7.0.12 (cli) (built: Oct 14 2016 09:56:59) ( NTS )
    Copyright (c) 1997-2016 The PHP Group
    Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    ------ Results: -------
    * 100 million iterations:
    $outstr = 'literal' . $n . $data . $int . $data . $float . $n;
    63608ms (34.7% slower)
    $outstr = "literal$n$data$int$data$float$n";
    47218ms (fastest)
    $outstr =<<<EOS
    literal$n$data$int$data$float$n
    EOS;
    47992ms (1.64% slower)
    $outstr = sprintf('literal%s%s%d%s%f%s', $n, $data, $int, $data, $float, $n);
    76629ms (62.3% slower)
    $outstr = sprintf('literal%s%5$s%2$d%3$s%4$f%s', $n, $int, $data, $float, $data, $n);
    96260ms (103.9% slower)
    * 10 million iterations (test adapted to see which of the two fastest methods were faster at adding a newline; either the PHP_EOL literal, or the \n string expansion):
    $outstr = 'literal' . $n . $data . $int . $data . $float . $n;
    6228ms (reference for single-quoted without newline)
    $outstr = "literal$n$data$int$data$float$n";
    4653ms (reference for double-quoted without newline)
    $outstr = 'literal' . $n . $data . $int . $data . $float . $n . PHP_EOL;
    6630ms (35.3% slower than double-quoted with \n newline)
    $outstr = "literal$n$data$int$data$float$n\n";
    4899ms (fastest at newlines)
    * 100 million iterations (a test intended to see which one of the two ${var} and {$var} double-quote styles is faster):
    $outstr = 'literal' . $n . $data . $int . $data . $float . $n;
    67048ms (38.2% slower)
    $outstr = "literal$n$data$int$data$float$n";
    49058ms (1.15% slower)
    $outstr = "literal{$n}{$data}{$int}{$data}{$float}{$n}"
    49221ms (1.49% slower)
    $outstr = "literal${n}${data}${int}${data}${float}${n}"
    48500ms (fastest; the differences are small but this held true across multiple runs of the test, and this was always the fastest variable encapsulation style)
    * 1 BILLION iterations (testing a completely literal string with nothing to parse in it):
    $outstr = 'literal string testing';
    23852ms (fastest)
    $outstr = "literal string testing";
    24222ms (1.55% slower)
    It blows my mind. The double-quoted strings "which look so $slow since they have to parse everything for \n backslashes and $dollar signs to do variable expansion", turned out to be the FASTEST string concatenation method in PHP - PERIOD!
    Single-quotes are only faster if your string is completely literal (with nothing to parse in it and nothing to concatenate), but the margin is very tiny and doesn't matter.
    So the "highest code performance" style rules are:
    1. Always use double-quoted strings for concatenation.
    2. Put your variables in "This is a {$variable} notation", because it's the fastest method which still allows complex expansions like "This {$var['foo']} is {$obj->awesome()}!". You cannot do that with the "${var}" style.
    3. Feel free to use single-quoted strings for TOTALLY literal strings such as array keys/values, variable values, etc, since they are a TINY bit faster when you want literal non-parsed strings. But I had to do 1 billion iterations to find a 1.55% measurable difference. So the only real reason I'd consider using single-quoted strings for my literals is for code cleanliness, to make it super clear that the string is literal.
    4. If you think another method such as sprintf() or 'this'.$var.'style' is more readable, and you don't care about maximizing performance, then feel free to use whatever concatenation method you prefer!
    Don't forget about new E_WARNING and E_NOTICE errors from PHP 7.1.x: they have been introduced when invalid strings are coerced using operators expecting numbers (+ - * / ** % << >> | & ^) or their assignment equivalents. An E_NOTICE is emitted when the string begins with a numeric value but contains trailing non-numeric characters, and an E_WARNING is emitted when the string does not contain a numeric value.
    Example:
    $foo = 1 + "bob-1.3e3"; 
    $foo = "10.2 pigs " + 1.0; 
    Will produce: Warning: A non-numeric value encountered
    Read more: https://www.php.net/manual/en/migration71.other-changes.php
    The documentation does not mention, but a closing semicolon at the end of the heredoc is actually interpreted as a real semicolon, and as such, sometimes leads to syntax errors.
    This works:
    <?php
    $foo = <<<END
    abcd
    END;
    ?>
    This does not:
    <?php
    foo(<<<END
    abcd
    END;
    );
    // syntax error, unexpected ';'
    ?>
    Without semicolon, it works fine:
    <?php
    foo(<<<END
    abcd
    END
    );
    ?>
    
    md5('240610708') == md5('QNKCDZO')
    This comparison is true because both md5() hashes start '0e' so PHP type juggling understands these strings to be scientific notation. By definition, zero raised to any power is zero.
    You can use string like array of char (like C)
    $a = "String array test";
    var_dump($a); 
    // Return string(17) "String array test"
    var_dump($a[0]); 
    // Return string(1) "S"
    // -- With array cast --
    var_dump((array) $a); 
    // Return array(1) { [0]=> string(17) "String array test"}
    var_dump((array) $a[0]); 
    // Return string(17) "S"
    - Norihiori
    You can use the complex syntax to put the value of both object properties AND object methods inside a string. For example...
    <?php
    class Test {
      public $one = 1;
      public function two() {
        return 2;
      }
    }
    $test = new Test();
    echo "foo {$test->one} bar {$test->two()}";
    ?>
    Will output "foo 1 bar 2".
    However, you cannot do this for all values in your namespace. Class constants and static properties/methods will not work because the complex syntax looks for the '$'.
    <?php
    class Test {
      const ONE = 1;
    }
    echo "foo {Test::ONE} bar";
    ?>
    This will output "foo {Test::one} bar". Constants and static properties require you to break up the string.
    Beware that consistent with "String conversion to numbers":
    <?php
    if ('123abc' == 123) echo '(intstr == int) incorrectly tests as true.';
    // Because one side is a number, the string is incorrectly converted from intstr to int, which then matches the test number.
    // True for all conditionals such as if and switch statements (probably also while loops)!
    // This could be a huge security risk when testing/using/saving user input, while expecting and testing for only an integer.
    // It seems the only fix is for 123 to be a string as '123' so no conversion happens.
    ?>
    
    Leading zeroes in strings are (least-surprise) not treated as octal.
    Consider:
     $x = "0123" + 0;  
     $y = 0123 + 0;
     echo "x is $x, y is $y";  //prints "x is 123, y is 83"
    in other words:
     * leading zeros in numeric literals in the source-code are interpreted as "octal", c.f. strtol().
     * leading zeros in strings (eg user-submitted data), when cast (implicitly or explicitly) to integer are ignored, and considered as decimal, c.f. strtod().
    easy transparent solution for using constants in the heredoc format:
    DEFINE('TEST','TEST STRING');
    $const = get_defined_constants();
    echo <<<END
    {$const['TEST']}
    END;
    Result:
    TEST STRING
    Here is an easy hack to allow double-quoted strings and heredocs to contain arbitrary expressions in curly braces syntax, including constants and other function calls:
    <?php
    // Hack declaration
    function _expr($v) { return $v; }
    $_expr = '_expr';
    // Our playground
    define('qwe', 'asd');
    define('zxc', 5);
    $a=3;
    $b=4;
    function c($a, $b) { return $a+$b; }
    // Usage
    echo "pre {$_expr(1+2)} post\n"; // outputs 'pre 3 post'
    echo "pre {$_expr(qwe)} post\n"; // outputs 'pre asd post'
    echo "pre {$_expr(c($a, $b)+zxc*2)} post\n"; // outputs 'pre 17 post'
    // General syntax is {$_expr(...)}
    ?>
    
    I though that it would be helpful to add this comment so that the information at least appears on the right page on the PHP site.
    Note that if you intend to use a double-quoted string with an associative key, you may run into the T_ENCAPSED_AND_WHITESPACE error. Some regard this as one of the less obvious error messages.
    An expression such as:
    <?php
      $fruit=array(
        'a'=>'apple',
        'b'=>'banana',
        //  etc
      );
      print "This is a $fruit['a']";  //  T_ENCAPSED_AND_WHITESPACE
    ?>
    will definitely fall to pieces.
    You can resolve it as follows:
    <?php
      print "This is a $fruit[a]";  //  unquote the key
      print "This is a ${fruit['a']}";  //  Complex Syntax
      print "This is a {$fruit['a']}";  //  Complex Syntax variation
    ?>
    I have a personal preference for the last variation as it is more natural and closer to what the expression would be like outside the string.
    It’s not clear (to me, at least) why PHP misinterprets the single quote inside the expression but I imagine that it has something to do with the fact quotes are not part of the value string — once the string is already being parsed the quotes just get in the way … ?
    Both should work :(
    <?php
    class Testing {
      public static $VAR = 'static';
      public const VAR = 'const';
      
      public function sayHelloStatic() {
        echo "hello: {$this::$VAR}";
      }
      
      public function sayHelloConst() {
        echo "hello: {$this::VAR}"; //Parse error: syntax error, unexpected '}', expecting '['
      }
    }
    $obj = new Testing();
    $obj->sayHelloStatic();
    $obj->sayHelloConst();
    Something I experienced which no doubt will help someone . . .
    In my editor, this will syntax highlight HTML and the $comment:
    $html = <<<"EOD"
    <b>$comment</b>
    EOD;
    Using this shows all the same colour:
    $html = <<<EOD
    <b>$comment</b>
    EOD;
    making it a lot easier to work with
    To save Your mind don't read previous comments about dates ;)
    When both strings can be converted to the numerics (in ("$a" > "$b") test) then resulted numerics are used, else FULL strings are compared char-by-char:
    <?php
    var_dump('1.22' > '01.23'); // bool(false)
    var_dump('1.22.00' > '01.23.00'); // bool(true)
    var_dump('1-22-00' > '01-23-00'); // bool(true)
    var_dump((float)'1.22.00' > (float)'01.23.00'); // bool(false)
    ?>
    
    Any single expression, however complex, that starts with $ (i.e., a variable) can be {}-embedded in a double-quoted string:
    <?php
    echo "The expression {$h->q()["x}"]->p(9 == 0 ? 17 : 42)} gets parsed just as well as " . $h->q()["x}"]->p(9 == 0 ? 17 : 42) . " does.";
    ?>
    
    Unlike bash, we can't do 
     echo "\a"    #beep!
    Of course, that would be rather meaningless for PHP/web, but it's useful for PHP-CLI. The solution is simple: echo "\x07"
    Simple function to create human-readably escaped double-quoted strings for use in source code or when debugging strings with newlines/tabs/etc.
    <?php
    function doubleQuote($str) {
      $ret = '"';
      for ($i = 0, $l = strlen($str); $i < $l; ++$i) {
        $o = ord($str[$i]);
        if ($o < 31 || $o > 126) {
          switch ($o) {
            case 9: $ret .= '\t'; break;
            case 10: $ret .= '\n'; break;
            case 11: $ret .= '\v'; break;
            case 12: $ret .= '\f'; break;
            case 13: $ret .= '\r'; break;
            default: $ret .= '\x' . str_pad(dechex($o), 2, '0', STR_PAD_LEFT);
          }
        } else {
          switch ($o) {
            case 36: $ret .= '\$'; break;
            case 34: $ret .= '\"'; break;
            case 92: $ret .= '\\\\'; break;
            default: $ret .= $str[$i];
          }
        }
      }
      return $ret . '"';
    }
    ?>
    
    String conversion to numbers.
    Unfortunately, the documentation is not correct.
    «The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero).
    It is not said and is not shown in examples throughout the documentation that, while converting strings to numbers, leading space characters are ignored, like with the strtod function.
    <?php
      echo "   \v\f  \r  1234" + 1;  // 1235
      var_export ("\v\f  \r  1234" == "1234");  // true
    ?>
    However, PHP's behaviour differs even from the strtod's. The documentation says that if the string contains a "e" or "E" character, it will be parsed as a float, and suggests to see the manual for strtod for more information. The manual says
    «A hexadecimal number consists of a "0x" or "0X" followed by a nonempty sequence of hexadecimal digits possibly containing a radix character, optionally followed by a binary exponent. A binary exponent consists of a 'P' or 'p', followed by an optional plus or minus sign, followed by a nonempty sequence of decimal digits, and indicates multiplication by a power of 2.
    But it seems that PHP does not recognise the exponent or the radix character.
    <?php
      echo "0xEp4" + 1;   // 15
    ?>
    strtod also uses the current locale to choose the radix character, but PHP ignores the locale, and the radix character is always 2E. However, PHP uses the locale while converting numbers to strings.
    With strtod, the current locale is also used to choose the space characters, I don't know about PHP.
    <?php
    // Its A Example for "Heredoc":
    $n = 10;
    $var_heredoc = <<<HEREDOC
    Its A String For "$var_heredoc" variable.
    heredoc can expanding variables.
    (example: $n)
    if you want not expanding, you need print " \ " befor variable.
    (example: /$n)
    heredoc can use " /n, /t, /r, ... ".
    heredoc = the string of double-qoutation;
        HEREDOC; -> its bad closing of heredoc!
    HEREDOC;
    // its a good closing of heredoc!
    ?>
    
    You may use heredoc syntax to comment out large blocks of code, as follows:
    <?php
    <<<_EOC
      // end-of-line comment will be masked... so will regular PHP:
      echo ($test == 'foo' ? 'bar' : 'baz'); 
      /* c-style comment will be masked, as will other heredocs (not using the same marker) */
      echo <<<EOHTML
    This is text you'll never see!    
    EOHTML;
      function defintion($params) {
        echo 'foo';
      }
      class definition extends nothing   {
        function definition($param) {
         echo 'do nothing';
        }    
      }
      how about syntax errors?; = gone, I bet.
    _EOC;
    ?>
    Useful for debugging when C-style just won't do. Also useful if you wish to embed Perl-like Plain Old Documentation; extraction between POD markers is left as an exercise for the reader.
    Note there is a performance penalty for this method, as PHP must still parse and variable substitute the string.
    If you want a parsed variable surrounded by curly braces, just double the curly braces:
    <?php
     $foo = "bar";
     echo "{{$foo}}";
    ?>
    will just show {bar}. The { is special only if followed by the $ sign and matches one }. In this case, that applies only to the inner braces. The outer ones are not escaped and pass through directly.
    I commented on a php bug feature request for a string expansion function and figured I should post somewhere it might be useful:
    using regex, pretty straightforward:
    <?php
    function stringExpand($subject, array $vars) {
      // loop over $vars map
      foreach ($vars as $name => $value) {
        // use preg_replace to match ${`$name`} or $`$name`
        $subject = preg_replace(sprintf('/\$\{?%s\}?/', $name), $value,
    $subject);
      }
      // return variable expanded string
      return $subject;
    }
    ?>
    using eval() and not limiting access to only certain variables (entire current symbol table including [super]globals):
    <?php
    function stringExpandDangerous($subject, array $vars = array(), $random = true) {
      
        // extract $vars into current symbol table
        extract($vars);
        
        $delim;
        // if requested to be random (default), generate delim, otherwise use predefined (trivially faster)
        if ($random)
          $delim = '___' . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . chr(mt_rand(65,90)) . '___';
        else
          $delim = '__ASDFZXCV1324ZXCV__'; // button mashing...
        
        // built the eval code
        $statement = "return <<<$delim\n\n" . $subject . "\n$delim;\n";
        
        // execute statement, saving output to $result variable
        $result = eval($statement);
        
        // if eval() returned FALSE, throw a custom exception
        if ($result === false)
          throw new EvalException($statement);
        
        // return variable expanded string
        return $result;
      }
    ?>
    I hope that helps someone, but I do caution against using the eval() route even if it is tempting. I don't know if there's ever a truely safe way to use eval() on the web, I'd rather not use it.
    Here is a possible gotcha related to oddness involved with accessing strings by character past the end of the string:
    $string = 'a';
    var_dump($string[2]); // string(0) ""
    var_dump($string[7]); // string(0) ""
    $string[7] === ''; // TRUE
    It appears that anything past the end of the string gives an empty string.. However, when E_NOTICE is on, the above examples will throw the message:
    Notice: Uninitialized string offset: N in FILE on line LINE
    This message cannot be specifically masked with @$string[7], as is possible when $string itself is unset.
    isset($string[7]); // FALSE
    $string[7] === NULL; // FALSE
    Even though it seems like a not-NULL value of type string, it is still considered unset.
    Use caution when you need white space at the end of a heredoc. Not only is the mandatory final newline before the terminating symbol stripped, but an immediately preceding newline or space character is also stripped.
    For example, in the following, the final space character (indicated by \s -- that is, the "\s" is not literally in the text, but is only used to indicate the space character) is stripped:
    $string = <<<EOT
    this is a string with a terminating space\s
    EOT;
    In the following, there will only be a single newline at the end of the string, even though two are shown in the text:
    $string = <<<EOT
    this is a string that must be
    followed by a single newline
    EOT;
    If you want to use a variable in an array index within a double quoted string you have to realize that when you put the curly braces around the array, everything inside the curly braces gets evaluated as if it were outside a string. Here are some examples:
    <?php
    $i = 0;
    $myArray[Person0] = Bob;
    $myArray[Person1] = George;
    // prints Bob (the ++ is used to emphasize that the expression inside the {} is really being evaluated.)
    echo "{$myArray['Person'.$i++]}<br>";
    // these print George
    echo "{$myArray['Person'.$i]}<br>";
    echo "{$myArray["Person{$i}"]}<br>";
    // These don't work
    echo "{$myArray['Person$i']}<br>";
    echo "{$myArray['Person'$i]}<br>";
    // These both throw fatal errors
    // echo "$myArray[Person$i]<br>";
    //echo "$myArray[Person{$i}]<br>";
    ?>
    

    上篇:Float 浮点型

    下篇:Array 数组