/

PHP Migrating to 7.2 7.3 7.4

PHP7.1 to PHP7.2

Argon2 password hashing support, class constant visibility, object type, and many more.

New Features 7.2

// 新的 object 类型
// 可用于逆变(contravariant)参数输入和协变(covariant)返回任何对象类型
// https://www.php.net/manual/zh/language.oop5.variance.php
// 协变使子类比父类方法能返回更具体的类型;逆变使子类比父类方法参数类型能接受更模糊的类型
function test(object $obj): object
{
return new SplQueue();
}
test(new StdClass());
// 抽象类可以重写被继承的抽象类的抽象方法
abstract class A
{
abstract function test(string $s);
}
abstract class B extends A
{
// overridden - 仍然保持参数的逆变和返回的逆变
abstract function test($s): int;
}
// 重写方法和接口实现的参数类型可以省略
// 仍然是符合LSP,这种参数类型是逆变
interface A
{
public function test(array $input);
}
class B implements A
{
// type omitted for $input
public function test($input){
return $input;
}
}
var_dump((new B())->test(1));
// PHP72 int(1)
//
// PHP71 Fatal error: Declaration of B::test($input) must be compatible with A::test(array $input)

Backward incompatible changes 7.2

// 防止 number_format() 返回负零
var_dump(number_format(-0.01));
// PHP72 string(1) "0"
//
// PHP71 string(2) "-0"
// 转换对象和数组中的数字键
$arr = [0 => 1];
$obj = (object) $arr;
var_dump($obj);
var_dump($obj->{'0'}, // 新写法
$obj->{0} // 新写法
);
// PHP72 object(stdClass)#1 (1) {
// ["0"]=>
// int(1)
// }
// int(1)
// int(1)
//
// PHP71 object(stdClass)#1 (1) {
// [0]=>
// int(1)
// }
// Notice: Undefined property: stdClass::$0


$obj = new class {
public function __construct()
{
$this->{1} = "value";
}
};
$arr = (array) $obj;
var_dump($arr);
var_dump($arr["1"]); // 整数 或者 字符串整数 含义相同
var_dump($arr[1]); // PHP71
var_dump($arr[0]);
// PHP72 array(1) {
// [1]=>
// string(2) "my"
// }
//
// PHP71 无法取整型字符串 key
// array(1) {
// ["1"]=>
// string(2) "my"
// }
// Notice: Undefined offset: 1
// Notice: Undefined offset: 1
// Notice: Undefined offset: 0

$a = [1.3 => "v1", 1.4 => "v2"];
var_dump($a);
// ALL array key float 会被转换为 int
// array(1) {
// [1]=>
// string(2) "v2"
// }
// get_class() 函数不再接受 null
var_dump(get_class(null));
// PHP72
// Warning: get_class() expects parameter 1 to be object
// bool(false)
//
// PHP71
// Warning: get_class() called without object from outside a class
// bool(false)
//
// PHP80
// Fatal error: Uncaught TypeError: get_class(): Argument #1 ($object) must be of type object, null given
// 计算非可数类型(non-countable)时发出警告
var_dump(
count(null), // NULL is not countable
count(1), // integers are not countable
count('abc'), // strings are not countable
count(new stdclass) // objects not implementing the Countable interface are not countable
);
// PHP72
// Warning: count(): Parameter must be an array or an object that implements Countable
//
// PHP71
// 无 Warning
//
// PHP80
// Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array
// 调用未定义的常量,现在会抛出一个 E_WARNING 错误(之前版本中为 E_NOTICE))
// PHP8 将不会转化成他们自身的字符串,同时抛出 Error 异常
var_dump(MY_CONST);
// PHP72
// Warning: Use of undefined constant MY_CONST - assumed 'MY_CONST'
// string(8) "MY_CONST"
//
// PHP71
// Notice: Use of undefined constant MY_CONST
// string(8) "MY_CONST"
//
// PHP80
// Fatal error: Uncaught Error: Undefined constant "MY_CONST"
// bcmod 任意精度数字取模,添加新增参数 scale
var_dump(bcmod("4", "3.5"));
// PHP72
// string(1) "0"
//
// PHP71
// string(1) "1"
var_dump(bcmod("4", "3.5", 1));
// PHP72
// string(3) "0.5"
//
// PHP71
// Warning: bcmod() expects exactly 2 parameters, 3 given
// json_decode associative 允许为 null
// 当为 true 时,JSON 对象将返回关联 array;当为 false 时,JSON 对象将返回 object。
// 当为 null 时,JSON 对象将返回关联 array 或 object,这取决于是否在 flags 中设置 JSON_OBJECT_AS_ARRAY
// https://www.php.net/manual/zh/function.json-decode.php
$json = '{"a":1,"b":2}';
var_dump(json_decode($json, null, 512, JSON_OBJECT_AS_ARRAY));
// PHP72
// array(2) {
// ["a"]=>
// int(1)
// ["b"]=>
// int(2)
// }
//
// PHP71
// object(stdClass)#1 (2) {
// ["a"]=>
// int(1)
// ["b"]=>
// int(2)
// }

PHP7.2 to PHP7.3

Heredoc/nowdoc syntax improvements and a bunch of legacy code deprecations.

New Features 7.3

// Heredoc Nowdoc 不再需要后跟分号或换行符
// 结束标记可以缩进,结束时所引用的标识符必须在该行的第一列
$values = [<<<END
a
b
c
END, 'd e f'];
var_dump($values);
// PHP73 array(2) {
// [0]=>
// string(13) "a
// b
// c"
// [1]=>
// string(5) "d e f"
// }
//
// PHP72 Parse error: syntax error, unexpected end of file

echo <<<END
a
b
c
END;
// PHP73
// a
// b
// c
//
// PHP72 Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T_END_HEREDOC) or ${ (T_DOLLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN)

echo <<<END
a
b
c
END;
// PHP73 Parse error: Invalid body indentation level
// 数组解构支持引用赋值
$arr = [[1], [1]];
[&$a, $b] = $arr;
$a[] = 2;
$b[] = 3;
var_dump($arr);
// PHP73 array(2) {
// [0]=>
// &array(2) {
// [0]=>
// int(1)
// [1]=>
// int(2)
// }
// [1]=>
// array(1) {
// [0]=>
// int(1)
// }
// }
//
// PHP72 Fatal error: [] and list() assignments cannot be by reference
// 允许将 literals 作为第一个操作数,always false
var_dump(true instanceof stdClass);
// PHP73 bool(false)
//
// PHP72 Fatal error: instanceof expects an object instance, constant given
// 调用中允许尾随逗号
function my($v) {
echo "php-{$v}";
}
my(73,);
// PHP73 php-73
//
// PHP72 Parse error: syntax error, unexpected ')'

New Functions 7.3

// Gets the first key of an array
array_key_first(array $array): int|string|null
// Gets the last key of an array
array_key_last(array $array): int|string|null
// Get the system's high resolution time
// [seconds, nanoseconds] int(64 位平台)或 float(32 位平台)
hrtime(bool $as_number = false): array|int|float|false
// 验证变量的内容是否为 countable 值
// return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement;
is_countable(mixed $value): bool

Backward Incompatible Changes 7.3

// Continue Targeting Switch 问题警告
$foo = 0;
while ($foo < 10) {
switch ($foo) {
case "baz":
continue;
}
$foo++;
}
// PHP73 Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?
// PHP72 ok
// $obj["123"] 类型的数组访问,其中 $obj 实现 ArrayAccess 且 "123" 是整数字符串文字将不再导致隐式转换为整数
// 数组的行为不会受到任何影响,它们继续将整数字符串键隐式转换为整数
class A implements \ArrayAccess
{
public function offsetExists($offset)
{
}
public function offsetGet($offset)
{
var_dump($offset);
}
public function offsetSet($offset, $value)
{
}
public function offsetUnset($offset)
{
}
}
$a = new A();
$a["123"];
// PHP73 string(3) "123"
// PHP72 int(123)

PHP7.3 to PHP7.4

PHP 7.4, the final release in the PHP 7.x series. PHP 7.4 brings typed properties, underscore numeric separator, and other minor improvements to PHP.

New Features 7.4

// Typed properties
class User {
public int $id; // 会强制要求 $user->id 只能为 int 类型,访问前必须进行处理化,?int 也要进行初始化
}
// 箭头函数 Arrow functions
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// 有限的 Limited 返回类型协变和参数类型逆变
class A {}
class B extends A {}
class Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
// PHP74 ok
// PHP73 Fatal error: Declaration of ChildProducer::method(): B must be compatible with Producer::method(): A
// 空合并赋值运算符
$array['key1'] ??= 1;
// is roughly equivalent to
if (!isset($array['key2'])) {
$array['key2'] = 2;
}
var_dump($array);
// array(2) {
// ["key1"]=>
// int(1)
// ["key2"]=>
// int(2)
// }
// Unpacking inside arrays
// 可以平替 array_merge
$parts = ['apple', 'pear'];
$fruits = ['orange', ...$parts, 'watermelon'];
var_dump($fruits);
// array(4) {
// [0]=>
// string(6) "orange"
// [1]=>
// string(5) "apple"
// [2]=>
// string(4) "pear"
// [3]=>
// string(10) "watermelon"
// }
// 数字文字分隔符
6.674_083e-11; // float
299_792_458; // decimal
0xCAFE_F00D; // hexadecimal
0b0101_1111; // binary

var_dump((int)"1_123");
// int(1)
// WeakReference 类
// https://www.php.net/manual/zh/class.weakreference.php
$obj = new stdClass;
$weakref = WeakReference::create($obj);
var_dump($weakref->get());
unset($obj);
var_dump($weakref->get());
// object(stdClass)#1 (0) {
// }
// NULL

Backward Incompatible Changes 7.4

// 以数组形式访问非数组,将会抛出 notic
// null, bool, int, float or resource
$i = 12;
$i["a"];
// PHP74 Notice: Trying to access array offset on value of type int
// PHP73 ok
// PHP80 Warning: Trying to access array offset on value of type int

Deprecated Features 7.4

// 嵌套的三元运算必须明确地使用括号来指示运算的顺序
var_dump(1 ? 2 : 3 ? 4 : 5);
// PHP74 Deprecated: Unparenthesized `a ? b : c ? d : e` is deprecated. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`
// PHP73 int(4)

– EOF –