前两天,PHP5.6已经发布了。恐怕我们很多人都停留在5.2时代吧。 PHP5.3 (2009-2012) PHP5.3 算是一个非常大的更新,新增了大量新特征,同时也做了一些不向下兼容的修改。 弃用的功能 以下几个功能被弃用,若在配置文件中启用,则 PHP 会在运行时发出警告。 R
前两天,PHP5.6已经发布了。恐怕我们很多人都停留在5.2时代吧。
(2009-2012)
PHP5.3 算是一个非常大的更新,新增了大量新特征,同时也做了一些不向下兼容的修改。
弃用的功能
以下几个功能被弃用,若在配置文件中启用,则 PHP 会在运行时发出警告。
这是 php.ini 中的一个选项(register_globals), 开启后会将所有表单变量($_GET和$_POST)注册为全局变量.
看下面的例子:
2 3 4 |
if(isAuth()) $authorized = true; include("page.php");
|
但由于并没有事先把 $authorized 初始化为 false, 当 register_globals 打开时,可能访问 /auth.php?authorized=1 来定义该变量值,绕过身份验证。
该特征属于历史遗留问题,在 PHP4.2 中被默认关闭,在 PHP5.4 中被移除。
Magic Quotes
1 2 3 4 5 6 |
$func = function($arg) { print $arg; };
$func("Hello World"); |
该特征会将所有用户输入进行转义,这看上去不错,在第一章我们提到过要对用户输入进行转义。
但是 PHP 并不知道哪些输入会进入 SQL , 哪些输入会进入 Shell, 哪些输入会被显示为 HTML, 所以很多时候这种转义会引起混乱。
Safe Mode
很多虚拟主机提供商使用 Safe Mode 来隔离多个用户,但 Safe Mode 存在诸多问题,例如某些扩展并不按照 Safe Mode 来进行权限控制。
PHP官方推荐使用操作系统的机制来进行权限隔离,让Web服务器以不同的用户权限来运行PHP解释器,请参见第一章中的最小权限原则.
匿名函数
也叫闭包(Closures), 经常被用来临时性地创建一个无名函数,用于回调函数等用途。
1 2 3 4 5 6 |
function arrayPlus($array, $num) { array_walk($array, function(&$v) use($num){ $v = $num; }); } |
1 2 3 4 5 6 | $func = function($arg) { print $arg; }; $func("Hello World"); |
1 2 3 4 5 6 | function arrayPlus($array, $num) { array_walk($array, function(&$v) use($num){ $v = $num; }); } |
上面的代码定义了一个 arrayPlus() 函数(这不是匿名函数), 它会将一个数组($array)中的每一项,加上一个指定的数字($num).
在 arrayPlus() 的实现中,我们使用了 array_walk() 函数,它会为一个数组的每一项执行一个回调函数,即我们定义的匿名函数。
在匿名函数的参数列表后,我们用 use 关键字将匿名函数外的 $num 捕捉到了函数内,以便知道到底应该加上多少。
PHP 的面向对象体系中,提供了若干“魔术方法”,用于实现类似其他语言中的“重载”,如在访问不存在的属性、方法时触发某个魔术方法。
随着匿名函数的加入,PHP 引入了一个新的魔术方法 __invoke().
该魔术方法会在将一个对象作为函数调用时被调用:
2 3 4
7 89
10
|
|
1 | A::__invoke(): Hello World |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php // 命名空间的分隔符是反斜杠,该声明语句必须在文件第一行。 // 命名空间中可以包含任意代码,但只有 **类, 函数, 常量** 受命名空间影响。 namespace XXOOTest; // 该类的完整限定名是 XXOOTestA , 其中第一个反斜杠表示全局命名空间。 class A{} // 你还可以在已经文件中定义第二个命名空间,接下来的代码将都位于 OtherTest2 . namespace OtherTest2; // 实例化来自其他命名空间的对象: $a = new XXOOTestA; class B{} // 你还可以用花括号定义第三个命名空间 namespace Other { // 实例化来自子命名空间的对象: $b = new Test2B; // 导入来自其他命名空间的名称,并重命名, // 注意只能导入类,不能用于函数和常量。 use XXOOTestA as ClassA } |
更多有关命名空间的语法介绍请参见PHP官网
命名空间时常和 autoload 一同使用,用于自动加载类实现文件:
2 4 5
|
spl_autoload_register( function ($class) {
} );
|
1 |
B::funcXXOO |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class A { public function callFuncXXOO() { print $this->funcXXOO(); } public function funcXXOO() { return "A::funcXXOO()"; } } class B extends A { public function funcXXOO() { return "B::funcXXOO"; } } $b = new B; $b->callFuncXXOO(); |
1 | B::funcXXOO |
可以看到,当在 A 中使用 $this->funcXXOO() 时,体现了“虚函数”的机制,实际调用的是 B::funcXXOO().
然而如果将所有函数都改为静态函数:
2 3 4
7
8 9
11 12 13
16 1718 19
20 21
|
class A { static public function callFuncXXOO() { print self::funcXXOO(); } static public function funcXXOO() { return "A::funcXXOO()"; } } class B extends A { static public function funcXXOO() { return "B::funcXXOO"; } } $b = new B; $b->callFuncXXOO(); |
1 | A::funcXXOO() |
1 2 3 4 5 6 7 8 9 10 11 | class A { static public function callFuncXXOO() { print static::funcXXOO(); } // ... } // ... |
1 | B::funcXXOO |
1 2 3 4 | $name = "MyName"; echo <<< TEXT My name is "{$name}". TEXT; |
Heredoc 以三个左尖括号开始,后面跟一个标识符(TEXT), 直到一个同样的顶格的标识符(不能缩进)结束。
就像双引号字符串一样,其中可以嵌入变量。
Heredoc 还可以用于函数参数,以及类成员初始化:
2 3 4
7
8 9
11 1213 14 15
|
EOD
);
{ const xx = <<< EOD Hello World
public $oo = <<< EOD Hello WorldEOD;
}
|
1 |
echo $a ? $a : "No Value"; |
|
$name = "MyName"; echo <<< 'TEXT' My name is "{$name}". TEXT; |
1 | My name is "{$name}". |
1 | define("XOOO", "Value"); |
1 | const XXOO = "Value"; |
1 2 3 4 | // 正确 const XXOO = 1234; // 错误 const XXOO = 2 * 617; |
1 | echo $a ? $a : "No Value"; |
1 | echo $a ?: "No Value"; |
即如果省略三元运算符的第二个部分,会默认用第一个部分代替。
Phar即PHP Archive, 起初只是Pear中的一个库而已,后来在PHP5.3被重新编写成C扩展并内置到 PHP 中。
Phar用来将多个 .php 脚本打包(也可以打包其他文件)成一个 .phar 的压缩文件(通常是ZIP格式)。
目的在于模仿 Java 的 .jar, 不对,目的是为了让发布PHP应用程序更加方便。同时还提供了数字签名验证等功能。
.phar 文件可以像 .php 文件一样,被PHP引擎解释执行,同时你还可以写出这样的代码来包含(require) .phar 中的代码:
2
|
require("xxoo.phar");require("phar://xxoo.phar/xo/ox.php"); |
更多信息请参见官网 [注].
注:http://www.php.net/manual/zh/phar.using.intro.php
PHP5.4
1 2 3 |
<?php // Code... ?> |
Short Open Tag 自 PHP5.4 起总是可用。
1 |
<? /* Code... */ ?> |
1 2 3
|
<?php // Code...
?>
|
1 |
<?= $xxoo;?> |
1 |
<? /* Code... */ ?>
|
还可以把
1 2 3 4 |
// 原来的数组写法 $arr = array("key" => "value", "key2" => "value2"); // 简写形式 $arr = ["key" => "value", "key2" => "value2"]; |
1 | <?php echo $xxoo;?> |
1 | <?= $xxoo;?> |
1 2 3 4 | // 原来的数组写法 $arr = array("key" => "value", "key2" => "value2"); // 简写形式 $arr = ["key" => "value", "key2" => "value2"]; |
所谓Traits就是“构件”,是用来替代继承的一种机制。PHP中无法进行多重继承,但一个类可以包含多个Traits.
2 4 56 7
8 9
11 13
14 15
17 18 |
// Traits不能被单独实例化,只能被类所包含 trait SayWorld {
echo 'World!';
} }
class MyHelloWorld { // 将SayWorld中的成员包含进来
|
1 | php -S localhost:8000 |
1 | php -S localhost:8000 index.php |
1 2 | $func = "funcXXOO"; A::{$func}(); |
1 | (new MyClass)->xxoo(); |
1 | print func()[0]; |
(2013起)
yield关键字用于当函数需要返回一个迭代器的时候, 逐个返回值。
2 34 5
|
for($i = 1; $i <= 10; $i = 1)
yield $i; }
|
该函数的返回值是一个数组:
可以用 list() 在 foreach 中解析嵌套的数组:
1 234
5 6
|
$array = [ [1, 2, 3],
|
1 2 | 1 2 3 4 5 6 |
1 2 3 4 5 6 7 8 | const A = 2; const B = A 1; class C { const STR = "hello"; const STR2 = self::STR ", world"; } |
1 | function func($arg = C::STR2) |
用来替代 func_get_args()
1 2 3 4 5 6 7 |
function add(...$args) { $result = 0; foreach($args as $arg) $result = $arg; return $result; } |
2
3
4
1 2 3 |
$arr = [2, 3]; add(1, ...$arr); // 结果为 6 |
7
函数add(...$args)
{
$结果= 0;
1 2 3 4 5 6 7 8 9 10 11 12 |
namespace NameSpace { const FOO = 42; function f() { echo __FUNCTION__."n"; } }
namespace { use const NameSpaceFOO; use function NameSpacef;
echo FOO."n"; f(); } |
$结果 = $arg; 返回$结果;
}