- 实验环境:https://onlinephp.io/
- Polyfill https://github.com/symfony/polyfill/tree/main/src
PHP7.0 to PHP7.1
https://www.php.net/manual/en/migration71.php
7.1 New Features
代码语言:javascript复制// Nullable types 可为空类型
function test(?string $name): ?string
代码语言:javascript复制// Void 函数
function swap(&$left, &$right) : void
// 获取一个 void 方法的返回值会得到 null,并且不会产生任何警告
代码语言:javascript复制// 对称数组解构
$data = [
[1, 'Tom'],
[2, 'Fred'],
];
[$id, $name] = $data[0];
// 赋值部分
[, $name1] = $data[1];
foreach ($data as [$id, $name]) {
// logic here with $id and $name
}
function swap(&$a, &$b): void
{
[$a, $b] = [$b, $a];
}
代码语言:javascript复制// list 支持键名
$data = [
["id" => 1, "name" => 'Tom'],
["id" => 2, "name" => 'Fred'],
];
foreach ($data as ["name" => $name, "id" => $id]) {
// logic here with $id and $name
}
代码语言:javascript复制// 类常量支持可见性
class ConstDemo
{
public const PUBLIC_CONST_A = 1;
}
代码语言:javascript复制// iterable 伪类(与 callable 类似)
interface Traversable extends iterable {
// 这个接口没有任何方法,它的作用仅仅是作为所有可遍历类的基本接口
// Traversable as part of either Iterator or IteratorAggregate,不能直接实现
}
function iterator(iterable $iter)
{
foreach ($iter as $val) {
// ...
}
}
代码语言:javascript复制// 多异常捕获处理,可以通过管道字符(|)来实现多个异常的捕获
try {
// some code
} catch (FirstException | SecondException $e) {
// handle first and second exceptions
}
代码语言:javascript复制// 支持为负的字符串偏移量,一个负数的偏移量会被理解为一个从字符串结尾开始的偏移量
// 所有支持偏移量的字符串操作函数,都支持接受负数作为偏移量
// 中文操作要小心
var_dump("abcdef"[-2]); // e
var_dump(strpos("aabbcc", "b")); // 2
var_dump(strpos("aabbcc", "b", -3)); // 3
代码语言:javascript复制// 新增 Closure::fromCallable(),将 callable 转为一个 Closure 对象
// public static Closure::fromCallable(callable $callback): Closure
class Test
{
public function exposeFunction()
{
return Closure::fromCallable([$this, 'privateFunction']);
}
private function privateFunction($param)
{
var_dump($param);
}
}
$privFunc = (new Test)->exposeFunction();
$privFunc('some value');
// string(10) "some value"
7.1 New Functions
代码语言:javascript复制// 否为可迭代
is_iterable()
7.1 Backward Incompatible Changes
代码语言:javascript复制// 当传递参数过少时将抛出错误
function test($param){}
test();
/*
PHP71
Fatal error: Uncaught ArgumentCountError: Too few arguments to function test()
PHP70
Warning: Missing argument 1 for test()
*/
代码语言:javascript复制// 禁止动态调用作用域自检函数
// $func() or array_map('extract', ...)
// function array_map($callback, array $array, array ...$arrays): array
(function () {
$func = 'func_num_args';
$func();
})();
/*
PHP71
Warning: Cannot call func_num_args() dynamically
*/
代码语言:javascript复制// 以下名称不能用于命名 class, interface, trait
// - void
// - iterable
代码语言:javascript复制// 数字字符串转换 遵循科学记数法
var_dump(intval('1e5'));
var_dump(is_numeric('1e5'));
var_dump(is_numeric('e'));
/*
PHP71
int(100000)
bool(true)
bool(false)
PHP70
int(1)
bool(true)
bool(false)
*/
代码语言:javascript复制// call_user_func() 不再支持对传址的函数的调用
error_reporting(E_ALL);
function increment(&$var)
{
$var ;
}
$a = 0;
call_user_func('increment', $a); // ...expected to be a reference, value given
call_user_func_array('increment', [&$a]); // 1
$increment = 'increment';
$increment($a); // 2
代码语言:javascript复制// 字符串不再支持空索引运算符
$str = "";
$str[] = "abc";
var_dump($str);
/*
PHP71
Fatal error: Uncaught Error: [] operator not supported for strings
PHP70
array(1) {
[0]=>
string(3) "abc"
}
*/
$a = "";
$a[0] = "hello world";
var_dump($a);
/*
PHP71
string(1) "h"
PHP70
array(1) {
[0]=>
string(11) "hello world"
}
*/
代码语言:javascript复制// 通过空字符串上的字符串索引访问赋值
$str = '';
$str[10] = 'foo';
var_dump($str);
/*
PHP71
string(11) " f"
PHP70
array(1) {
[10]=>
string(3) "foo"
}
*/
代码语言:javascript复制// 当通过引用赋值引用它们自动创建这些元素时,数组中元素的顺序已更改。
$array = [];
$array['a'] = &$array['b'];
$array['b'] = 1;
var_dump($array);
/*
PHP71
array(2) {
["b"]=>
&int(1)
["a"]=>
&int(1)
}
PHP70
array(2) {
["a"]=>
&int(1)
["b"]=>
&int(1)
}
*/
代码语言:javascript复制// 词法绑定变量不能重用名称,以下都将 fatal error
$f = function () use ($_SERVER) {}; // any superglobals
$f = function () use ($this) {};
$f = function ($param) use ($param) {};
代码语言:javascript复制// 禁止 "return;" 对于已经在编译时键入的返回值
function test(int $i): array
{
$i = 1;
return;
}
// PHP Compile Error A function with return type must return a value
代码语言:javascript复制var_dump('1b' 'something');
/*
PHP71
Notice: A non well formed numeric value encountered
Warning: A non-numeric value encountered
int(1)
PHP70
int(1)
*/
PHP5.6 to PHP7.0
https://www.php.net/manual/en/migration70.php
Backward incompatible changes
代码语言:javascript复制// 错误和异常处理相关的变更
// set_exception_handler() 不再保证收到的一定是 Exception 对象
function handler(Exception $e) { ... }
set_exception_handler('handler');
// 兼容 PHP 5 和 7
function handler($e) { ... }
// 仅支持 PHP 7
function handler(Throwable $e) { ... }
// 当内部构造器失败的时候,总是抛出异常
代码语言:javascript复制// 间接调用的表达式的新旧解析顺序
// 现在严格遵循从左到右的顺序来解析
// 表达式 PHP 5 的解析方式 PHP 7 的解析方式
$$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']
$foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']
代码语言:javascript复制// foreach 通过值遍历时,操作的值为数组的副本
$array = [0];
foreach ($array as $val) {
var_dump($val);
$array[1] = 1;
}
// int(0)
// foreach通过引用遍历时,有更好的迭代特性
$array = [0];
foreach ($array as &$val) {
var_dump($val);
$array[1] = 1;
}
// PHP 7.0
// int(0)
// int(1)
// PHP 5.6
// int(0)
代码语言:javascript复制// call_user_method() and call_user_method_array() 被移除。
// 应该使用 call_user_func() 和 call_user_func_array()
代码语言:javascript复制// 在函数中检视参数值会返回 当前 的值
function foo($x) {
$x ;
var_dump(func_get_arg(0));
}
foo(1);
// int(2) PHP 7.0
// int(1) PHP 5.6
7.0 New Features
代码语言:javascript复制// 标量类型声明
// 返回值类型声明
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
代码语言:javascript复制// null 合并运算符,对 isset() 的简化
$username = $_GET['user'] ?? 'nobody';
// 太空船操作符(组合比较符)
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
代码语言:javascript复制// 通过 define() 定义 常量数组
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
代码语言:javascript复制// 匿名类 用来替代一些“用后即焚”的完整类定义
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
代码语言:javascript复制// Unicode codepoint 转译语法
// 这接受一个以 16 进制形式的 Unicode codepoint
echo "u{9999}"; // 香
代码语言:javascript复制// Closure::call() 新方法,简化绑定一个方法到对象上闭包并调用它
// PHP 7 之前版本的代码
$getXCB = function() {return $this->x;};
// function bindTo($newThis, $newScope = 'static') { }
// $newScope 将闭包关联到的类作用域
$getX = $getXCB->bindTo(new A, A::class); // 中间层闭包
echo $getX();
// PHP 7 及更高版本的代码
$getX = function() {return $this->x;};
echo $getX->call(new A);
代码语言:javascript复制// 生成器委托 yield from
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
// 1
// 2
// 3
// 4
代码语言:javascript复制// 柯里化
function add($a) {
return function($b) use ($a) {
return $a $b;
};
}
$result = add(10)(15);
var_dump($result); // int 25
Deprecated features in PHP 7.0.x
代码语言:javascript复制// 构造函数(方法名和类名一样)将被弃用,并在将来移除
class Foo {
function foo() {
echo 'I am the constructor';
}
}
// PHP 7.0: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP
// PHP 5.6: OK
Other Changes
代码语言:javascript复制// 放宽了保留词限制,以前不能用 'new'、'private' 和 'for'
Project::new('Project Name')->private()->for('purpose here')->with('username here');
// class 关键词不能用于常量名,否则会和类名解析语法冲突(ClassName::class)
New Global Constants
代码语言:javascript复制PHP_INT_MIN
– EOF –
- # php