/

PHP Migrating to 7.0 7.1

PHP7.0 to PHP7.1

https://www.php.net/manual/en/migration71.php

7.1 New Features

// Nullable types 可为空类型
function test(?string $name): ?string
// Void 函数
function swap(&$left, &$right) : void
// 获取一个 void 方法的返回值会得到 null,并且不会产生任何警告
// 对称数组解构
$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];
}
// list 支持键名
$data = [
["id" => 1, "name" => 'Tom'],
["id" => 2, "name" => 'Fred'],
];
foreach ($data as ["name" => $name, "id" => $id]) {
// logic here with $id and $name
}
// 类常量支持可见性
class ConstDemo
{
public const PUBLIC_CONST_A = 1;
}
// iterable 伪类(与 callable 类似)
interface Traversable extends iterable {
// 这个接口没有任何方法,它的作用仅仅是作为所有可遍历类的基本接口
// Traversable as part of either Iterator or IteratorAggregate,不能直接实现
}

function iterator(iterable $iter)
{
foreach ($iter as $val) {
// ...
}
}
// 多异常捕获处理,可以通过管道字符(|)来实现多个异常的捕获
try {
// some code
} catch (FirstException | SecondException $e) {
// handle first and second exceptions
}
// 支持为负的字符串偏移量,一个负数的偏移量会被理解为一个从字符串结尾开始的偏移量
// 所有支持偏移量的字符串操作函数,都支持接受负数作为偏移量
// 中文操作要小心
var_dump("abcdef"[-2]); // e
var_dump(strpos("aabbcc", "b")); // 2
var_dump(strpos("aabbcc", "b", -3)); // 3
// 新增 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

// 否为可迭代
is_iterable()

7.1 Backward Incompatible Changes

// 当传递参数过少时将抛出错误
function test($param){}
test();
/*
PHP71
Fatal error: Uncaught ArgumentCountError: Too few arguments to function test()

PHP70
Warning: Missing argument 1 for test()
*/
// 禁止动态调用作用域自检函数
// $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
*/
// 以下名称不能用于命名 class, interface, trait
// - void
// - iterable
// 数字字符串转换 遵循科学记数法
var_dump(intval('1e5'));
/*
PHP71
int(100000)

PHP70
int(1)
*/
// 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
// 字符串不再支持空索引运算符
$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"
}
*/
// 通过空字符串上的字符串索引访问赋值
$str = '';
$str[10] = 'foo';
var_dump($str);
/*
PHP71
string(11) " f"

PHP70
array(1) {
[10]=>
string(3) "foo"
}
*/
// 当通过引用赋值引用它们自动创建这些元素时,数组中元素的顺序已更改。
$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)
}
*/
// 词法绑定变量不能重用名称,以下都将 fatal error
$f = function () use ($_SERVER) {}; // any superglobals
$f = function () use ($this) {};
$f = function ($param) use ($param) {};
// 禁止 "return;" 对于已经在编译时键入的返回值
function test(int $i): array
{
$i += 1;
return;
}
// PHP Compile Error A function with return type must return a value
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

// 错误和异常处理相关的变更
// set_exception_handler() 不再保证收到的一定是 Exception 对象
function handler(Exception $e) { ... }
set_exception_handler('handler');

// 兼容 PHP 5 和 7
function handler($e) { ... }

// 仅支持 PHP 7
function handler(Throwable $e) { ... }

// 当内部构造器失败的时候,总是抛出异常
// 间接调用的表达式的新旧解析顺序
// 现在严格遵循从左到右的顺序来解析
// 表达式 PHP 5 的解析方式 PHP 7 的解析方式
$$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']
$foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']
// 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)
// call_user_method() and call_user_method_array() 被移除。
// 应该使用 call_user_func() 和 call_user_func_array()
// 在函数中检视参数值会返回 当前 的值
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

// 标量类型声明
// 返回值类型声明
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
// null 合并运算符,对 isset() 的简化
$username = $_GET['user'] ?? 'nobody';

// 太空船操作符(组合比较符)
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// 通过 define() 定义 常量数组
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
// 匿名类 用来替代一些“用后即焚”的完整类定义
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
// Unicode codepoint 转译语法
// 这接受一个以 16 进制形式的 Unicode codepoint
echo "\u{9999}"; // 香
// 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);
// 生成器委托 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
// 柯里化
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

// 构造函数(方法名和类名一样)将被弃用,并在将来移除
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

// 放宽了保留词限制,以前不能用 'new'、'private' 和 'for'
Project::new('Project Name')->private()->for('purpose here')->with('username here');
// class 关键词不能用于常量名,否则会和类名解析语法冲突(ClassName::class)

New Global Constants

PHP_INT_MIN

– EOF –