As of now (2014.2), the latest stable version of PHP is PHP5.5, but almost half of the users are still using PHP5.2 which is no longer maintained [note], and the remaining half of the users are Use PHP5.3 [Note].
Because of PHP's painful syntax that "gathers the strengths of hundreds of schools of thought" and the poor community atmosphere, many people are not interested in new versions and new features.
This article will introduce the new features added in PHP5.2 starting from PHP5.6.
<span>function</span> __autoload(<span>$classname</span><span>) { </span><span>require_once</span>("{<span>$classname</span>}.php"<span>) }</span>
spl_autoload_register(<span>function</span>(<span>$classname</span><span>) { </span><span>require_once</span>("{<span>$classname</span>}.php"<span>) });</span>
<span>//</span><span> 连接到服务器,选择数据库</span> <span>$conn</span> = <span>mysql_connect</span>("localhost", "user", "password"<span>); </span><span>mysql_select_db</span>("database"<span>); </span><span>//</span><span> 执行 SQL 查询</span> <span>$type</span> = <span>$_POST</span>['type'<span>]; </span><span>$sql</span> = "SELECT * FROM `table` WHERE `type` = {<span>$type</span>}"<span>; </span><span>$result</span> = <span>mysql_query</span>(<span>$sql</span><span>); </span><span>//</span><span> 打印结果</span> <span>while</span>(<span>$row</span> = <span>mysql_fetch_array</span>(<span>$result</span>,<span> MYSQL_ASSOC)) { </span><span>foreach</span>(<span>$row</span> <span>as</span> <span>$k</span> => <span>$v</span><span>) </span><span>print</span> "{<span>$k</span>}: {<span>$v</span>}\n"<span>; } </span><span>//</span><span> 释放结果集,关闭连接</span> <span>mysql_free_result</span>(<span>$result</span><span>); </span><span>mysql_close</span>(<span>$conn</span>);
为了能够让代码实现数据库无关,即一段代码同时适用于多种数据库(例如以上代码仅仅适用于MySQL),PHP 官方设计了 PDO.
<span>//</span><span> 连接到数据库</span> <span>$conn</span> = <span>new</span> PDO("mysql:host=localhost;dbname=database", "user", "password"<span>); </span><span>//</span><span> 预编译SQL, 绑定参数</span> <span>$query</span> = <span>$conn</span>->prepare("SELECT * FROM `table` WHERE `type` = :type"<span>); </span><span>$query</span>->bindParam("type", <span>$_POST</span>['type'<span>]); </span><span>//</span><span> 执行查询并打印结果</span> <span>foreach</span>(<span>$query</span>->execute() <span>as</span> <span>$row</span><span>) { </span><span>foreach</span>(<span>$row</span> <span>as</span> <span>$k</span> => <span>$v</span><span>) </span><span>print</span> "{<span>$k</span>}: {<span>$v</span>}\n"<span>; }</span>
<span>//</span><span> 限制第一个参数为 MyClass, 第二个参数为可执行类型,第三个参数为数组</span> <span>function</span> MyFunction(MyClass <span>$a</span>, callable <span>$b</span>, <span>array</span> <span>$c</span><span>) { </span><span>//</span><span> ...</span> }
<span>$array</span> = <span>array</span>("key" => "value", "array" => <span>array</span>(1, 2, 3, 4<span>)); </span><span>$json</span> = json_encode(<span>$array</span><span>); </span><span>echo</span> "{<span>$json</span>}\n"<span>; </span><span>$object</span> = json_decode(<span>$json</span><span>); </span><span>print_r</span>(<span>$object</span>);
{"key":"value","array":[1,2,3,4<span>]} stdClass </span><span>Object</span><span> ( [</span><span>key</span>] =><span> value [</span><span>array</span>] => <span>Array</span><span> ( [</span>0] => 1<span> [</span>1] => 2<span> [</span>2] => 3<span> [</span>3] => 4<span> ) )</span>
<span>if</span><span>(isAuth()) </span><span>$authorized</span> = <span>true</span><span>; </span><span>if</span>(<span>$authorized</span><span>) </span><span>include</span>("page.php");
<span>$func</span> = <span>function</span>(<span>$arg</span><span>) { </span><span>print</span> <span>$arg</span><span>; }; </span><span>$func</span>("Hello World");
<span>function</span> arrayPlus(<span>$array</span>, <span>$num</span><span>) { </span><span>array_walk</span>(<span>$array</span>, <span>function</span>(&<span>$v</span>) <span>use</span>(<span>$num</span><span>){ </span><span>$v</span> += <span>$num</span><span>; }); }</span>
<span>class</span><span> A { </span><span>public</span> <span>function</span> __invoke(<span>$str</span><span>) { </span><span>print</span> "A::__invoke(): {<span>$str</span>}"<span>; } } </span><span>$a</span> = <span>new</span><span> A; </span><span>$a</span>("Hello World");
A::__invoke(): Hello World
<?<span>php </span><span>//</span><span> 命名空间的分隔符是反斜杠,该声明语句必须在文件第一行。 // 命名空间中可以包含任意代码,但只有 **类, 函数, 常量** 受命名空间影响。</span> <span> namespace XXOO\Test; </span><span>//</span><span> 该类的完整限定名是 \XXOO\Test\A , 其中第一个反斜杠表示全局命名空间。</span> <span>class</span><span> A{} </span><span>//</span><span> 你还可以在已经文件中定义第二个命名空间,接下来的代码将都位于 \Other\Test2 .</span> <span> namespace Other\Test2; </span><span>//</span><span> 实例化来自其他命名空间的对象:</span> <span>$a</span> = <span>new</span><span> \XXOO\Test\A; </span><span>class</span><span> B{} </span><span>//</span><span> 你还可以用花括号定义第三个命名空间</span> <span> namespace Other { </span><span>//</span><span> 实例化来自子命名空间的对象:</span> <span>$b</span> = <span>new</span><span> Test2\B; </span><span>//</span><span> 导入来自其他命名空间的名称,并重命名, // 注意只能导入类,不能用于函数和常量。</span> <span>use</span> \XXOO\Test\A <span>as</span><span> ClassA }</span>
更多有关命名空间的语法介绍请参见官网 [注].
<span> spl_autoload_register( </span><span>function</span> (<span>$class</span><span>) { spl_autoload(</span><span>str_replace</span>("\\", "/", <span>$class</span><span>)); } );</span>
<span>class</span><span> A { </span><span>public</span> <span>function</span><span> callFuncXXOO() { </span><span>print</span> <span>$this</span>-><span>funcXXOO(); } </span><span>public</span> <span>function</span><span> funcXXOO() { </span><span>return</span> "A::funcXXOO()"<span>; } } </span><span>class</span> B <span>extends</span><span> A { </span><span>public</span> <span>function</span><span> funcXXOO() { </span><span>return</span> "B::funcXXOO"<span>; } } </span><span>$b</span> = <span>new</span><span> B; </span><span>$b</span>->callFuncXXOO();
输出是:
B::funcXXOO
<span>class</span><span> A { </span><span>static</span> <span>public</span> <span>function</span><span> callFuncXXOO() { </span><span>print</span> self::<span>funcXXOO(); } </span><span>static</span> <span>public</span> <span>function</span><span> funcXXOO() { </span><span>return</span> "A::funcXXOO()"<span>; } } </span><span>class</span> B <span>extends</span><span> A { </span><span>static</span> <span>public</span> <span>function</span><span> funcXXOO() { </span><span>return</span> "B::funcXXOO"<span>; } } </span><span>$b</span> = <span>new</span><span> B; </span><span>$b</span>->callFuncXXOO();
情况就没这么乐观了,输出是:
A::funcXXOO()
这是因为 self 的语义本来就是“当前类”,所以 PHP5.3 给 static 关键字赋予了一个新功能:后期静态绑定:
<span>class</span><span> A { </span><span>static</span> <span>public</span> <span>function</span><span> callFuncXXOO() { </span><span>print</span> <span>static</span>::<span>funcXXOO(); } </span><span>//</span><span> ...</span> <span> } </span><span>//</span><span> ...</span>
B::funcXXOO
<span>$name</span> = "MyName"<span>; </span><span>echo</span> <<<<span> TEXT My name is </span>"{<span>$name</span>}".<span> TEXT;</span>
<span>var_dump</span>(<<<<span>EOD Hello World EOD ); </span><span>class</span><span> A { </span><span>const</span> xx = <<<<span> EOD Hello World EOD; </span><span>public</span> <span>$oo</span> = <<<<span> EOD Hello World EOD; }</span>
Nowdoc 的行为像一个单引号字符串,不能在其中嵌入变量,和 Heredoc 唯一的区别就是,三个左尖括号后的标识符要以单引号括起来:
<span>$name</span> = "MyName"<span>; </span><span>echo</span> <<< 'TEXT'<span> My name is </span>"{<span>$name</span>}".<span> TEXT;</span>
My name is "{<span>$name</span>}".
<span>define</span>("XOOO", "Value");
<span>const</span> XXOO = "Value";
<span>//</span><span> 正确</span> <span>const</span> XXOO = 1234<span>; </span><span>//</span><span> 错误</span> <span>const</span> XXOO = 2 * 617;
<span>echo</span> <span>$a</span> ? <span>$a</span> : "No Value";
<span>echo</span> <span>$a</span> ?: "No Value";
<span>require</span>("xxoo.phar"<span>); </span><span>require</span>("phar://xxoo.phar/xo/ox.php");
<?<span>php </span><span>//</span><span> Code...</span> ?>
<? <span>/*</span><span> Code... </span><span>*/</span> ?>
<?php <span>echo</span> <span>$xxoo</span>;?>
<?= <span>$xxoo</span>;?>
<span>//</span><span> 原来的数组写法</span> <span>$arr</span> = <span>array</span>("key" => "value", "key2" => "value2"<span>); </span><span>//</span><span> 简写形式</span> <span>$arr</span> = ["key" => "value", "key2" => "value2"];
<span>//</span><span> Traits不能被单独实例化,只能被类所包含</span> <span> trait SayWorld { </span><span>public</span> <span>function</span><span> sayHello() { </span><span>echo</span> 'World!'<span>; } } </span><span>class</span><span> MyHelloWorld { </span><span>//</span><span> 将SayWorld中的成员包含进来</span> <span>use</span><span> SayWorld; } </span><span>$xxoo</span> = <span>new</span><span> MyHelloWorld(); </span><span>//</span><span> sayHello() 函数是来自 SayWorld 构件的</span> <span>$xxoo</span>->sayHello();
Traits还有很多神奇的功能,比如包含多个Traits, 解决冲突,修改访问权限,为函数设置别名等等。
php -S localhost:8000
php -S localhost:8000 index.php
<span>$func</span> = "funcXXOO"<span>; A</span>::{<span>$func</span>}();
(<span>new</span> MyClass)->xxoo();
<span>print</span> func()[0];
<span>function</span><span> number10() { </span><span>for</span>(<span>$i</span> = 1; <span>$i</span> <= 10; <span>$i</span> += 1<span>) yield </span><span>$i</span><span>; }</span>
<span>$array</span> =<span> [ [</span>1, 2, 3],<span> [</span>4, 5, 6],<span> ]; </span><span>foreach</span> (<span>$array</span> <span>as</span> <span>list</span>(<span>$a</span>, <span>$b</span>, <span>$c</span><span>)) </span><span>echo</span> "{<span>$a</span>} {<span>$b</span>} {<span>$c</span>}\n";
1 2 3 4 5 6
<span>const</span> A = 2<span>; </span><span>const</span> B = A + 1<span>; </span><span>class</span><span> C { </span><span>const</span> STR = "hello"<span>; </span><span>const</span> STR2 = self::STR + ", world"<span>; }</span>
<span>function</span> func(<span>$arg</span> = C::STR2)
<span>function</span> add(...<span>$args</span><span>) { </span><span>$result</span> = 0<span>; </span><span>foreach</span>(<span>$args</span> <span>as</span> <span>$arg</span><span>) </span><span>$result</span> += <span>$arg</span><span>; </span><span>return</span> <span>$result</span><span>; }</span>
<span>$arr</span> = [2, 3<span>]; add(</span>1, ...<span>$arr</span><span>); </span><span>//</span><span> 结果为 6</span>
<span> namespace Name\Space { </span><span>const</span> FOO = 42<span>; </span><span>function</span> f() { <span>echo</span> <span>__FUNCTION__</span>."\n"<span>; } } namespace { </span><span>use</span> <span>const</span><span> Name\Space\FOO; </span><span>use</span> <span>function</span><span> Name\Space\f; </span><span>echo</span> FOO."\n"<span>; f(); }</span>