PHP 7.0.x#
说明
本文部分内容根据官网进行删减,仅整理常用特性。
1. 新特性#
1.1. 标量类型声明#
标量 类型声明 有两种模式: 强制 (默认) 和 严格模式。 现在可以使用下列类型参数(无论用强制模式还是严格模式): 字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool)。它们扩充了PHP5中引入的其他类型:类名,接口,数组和 回调类型。
<?php
// Coercive mode
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
var_dump(sumOfInts(2, '3', 4.1));
以上例程会输出:
int(9)
要使用严格模式,一个 declare 声明指令必须放在文件的顶部。这意味着严格声明标量是基于文件可配的。 这个指令不仅影响参数的类型声明,也影响到函数的返回值声明(参见 返回值类型声明, 内置的PHP函数以及扩展中加载的PHP函数)
完整的标量类型声明文档和示例参见类型声明章节。
1.2. 返回值类型声明#
PHP 7 增加了对返回类型声明的支持。 类似于参数类型声明,返回类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同。
<?php
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
以上例程会输出:
Array
(
[0] => 6
[1] => 15
[2] => 24
)
完整的标量类型声明文档和示例可参见 返回值类型声明.
1.3. null合并运算符#
由于日常使用中存在大量同时使用三元表达式和 isset() 的情况, 我们添加了 null
合并运算符 (??
) 这个语法糖。如果变量存在且值不为 NULL
, 它就会返回自身的值,否则返回它的第二个操作数。
<?php
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// Coalesces can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>
1.4. 太空船操作符(组合比较符)#
太空船操作符用于比较两个表达式。当 $a
小于、等于或大于 $b
时它分别返回-1、0或1。 比较的原则是沿用 PHP 的常规比较规则进行的。
<?php
// 整数
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// 浮点数
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// 字符串
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
1.5. 通过 define() 定义常量数组#
Array 类型的常量现在可以通过 define() 来定义。在 PHP5.6 中仅能通过 const 定义。
<?php
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // 输出 "cat"
?>
1.6. 匿名类#
现在支持通过 new class
来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
?>
以上例程会输出:
object(class@anonymous)#2 (0) {
}
详细文档可以参考 匿名类.
1.7. Closure::call()
#
Closure::call()
现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。
<?php
class A {private $x = 1;}
// PHP 7 之前版本的代码
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // 中间层闭包
echo $getX();
// PHP 7+ 及更高版本的代码
$getX = function() {return $this->x;};
echo $getX->call(new A);
以上例程会输出:
1
1
1.8. 为 unserialize() 提供过滤#
这个特性旨在提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入。
<?php
// 将所有的对象都转换为 __PHP_Incomplete_Class 对象
$data = unserialize($foo, ["allowed_classes" => false]);
// 将除 MyClass 和 MyClass2 之外的所有对象都转换为 __PHP_Incomplete_Class 对象
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]);
// 默认情况下所有的类都是可接受的,等同于省略第二个参数
$data = unserialize($foo, ["allowed_classes" => true]);
1.9. Group use declarations#
从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入了。
<?php
// PHP 7 之前的代码
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// PHP 7+ 及更高版本的代码
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
?>
1.10. 整数除法函数 intdiv()#
新加的函数 intdiv() 用来进行 整数的除法运算。
<?php
var_dump(intdiv(10, 3));
?>
以上例程会输出:
int(3)
1.11. 会话选项#
session_start() 可以接受一个 array 作为参数, 用来覆盖 php.ini
文件中设置的 会话配置选项。
在调用 session_start() 的时候, 传入的选项参数中也支持 session.lazy_write 行为, 默认情况下这个配置项是打开的。它的作用是控制 PHP 只有在会话中的数据发生变化的时候才 写入会话存储文件,如果会话中的数据没有发生改变,那么 PHP 会在读取完会话数据之后, 立即关闭会话存储文件,不做任何修改,可以通过设置 read_and_close
来实现。
例如,下列代码设置 session.cache_limiter 为 private
,并且在读取完毕会话数据之后马上关闭会话存储文件。
<?php
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
?>
1.12. preg_replace_callback_array()#
在 PHP 7 之前,当使用 preg_replace_callback() 函数的时候, 由于针对每个正则表达式都要执行回调函数,可能导致过多的分支代码。 而使用新加的 preg_replace_callback_array() 函数, 可以使得代码更加简洁。
现在,可以使用一个关联数组来对每个正则表达式注册回调函数, 正则表达式本身作为关联数组的键, 而对应的回调函数就是关联数组的值。
1.13. CSPRNG Functions#
新加入两个跨平台的函数: random_bytes() 和 random_int() 用来产生高安全级别的随机字符串和随机整数。
1.14. 可以使用 list() 函数来展开实现了 ArrayAccess
接口的对象#
在之前版本中,list() 函数不能保证 正确的展开实现了 ArrayAccess
接口的对象, 现在这个问题已经被修复。
1.15. 其他特性#
允许在克隆表达式上访问对象成员,例如: (clone $foo)->bar()
。
2. 弃用的功能#
2.1. PHP4 风格的构造函数#
PHP4 风格的构造函数(方法名和类名一样)将被弃用,并在将来移除。 如果在类中仅使用了 PHP4 风格的构造函数,PHP7 会产生 E_DEPRECATED
警告。 如果还定义了 __construct()
方法则不受影响。
<?php
class foo {
function foo() {
echo 'I am the constructor';
}
}
?>
以上例程会输出:
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in example.php on line 3
2.2. 静态调用非静态的方法#
废弃了 静态(Static) 调用未声明成 static
的方法,未来可能会彻底移除该功能。
<?php
class foo {
function bar() {
echo 'I am not static!';
}
}
foo::bar();
?>
以上例程会输出:
Deprecated: Non-static method foo::bar() should not be called statically in - on line 8
I am not static!
2.3. password_hash() 盐值选项#
废弃了 password_hash() 函数中的盐值选项,阻止开发者生成自己的盐值(通常更不安全)。 开发者不传该值时,该函数自己会生成密码学安全的盐值。因此再无必要传入自己自定义的盐值。
原文
- 新特性:http://php.net/manual/zh/migration70.new-features.php
- 弃用的功能:http://php.net/manual/zh/migration70.deprecated.php