PHP7新特性和变化
php7出了不少语法糖和新操作,让我们来看看代码中常用的一些骚东西,拥抱变化!
PHP7.0新特性
组合比较符 <=>
组合比较符号用于比较两个表达式。当 $a
小于、等于或大于 $b
时它分别返回-1、0或1,比较规则延续常规比较规则。对象不能进行比较
var_dump('PHP' <=> 'Node'); // int(1) var_dump(123 <=> 456); // int(-1) var_dump(['a', 'b'] <=> ['a', 'b']); // int(0)
null合并运算符
由于日常使用中存在大量同时使用三元表达式和isset
操作。使用null
合并运算符可以简化操作
# php7以前 if(isset($_GET['a'])) { $a = $_GET['a']; } # php7以前 $a = isset($_GET['a']) ? $_GET['a'] : 'none'; #PHP 7 $a = $_GET['a'] ?? 'none';
变量类型声明
变量类型声明有两种模式。一种是强制的,和严格的。允许使用下列类型参数int
、string
、float
、bool
同时不能再使用int
、string
、float
、bool
作为类的名字了
function sumOfInts(int ...$ints) { return array_sum($ints); } var_dump(sumOfInts(2, '3', 4.1)); // int(9) # 严格模式 declare(strict_types=1); function add(int $x, int $y) { return $x + $y; } var_dump(add('2', 3)); // Fatal error: Argument 1 passed to add() must be of the type integer
返回值类型声明
增加了返回类型声明,类似参数类型。这样更方便的控制函数的返回值.在函数定义的后面加上:类型名即可
function fun(int $a): array { return $a; } fun(3);//Fatal error
匿名类
php7
允许 new class {}
创建一个匿名的对象。
//php7以前 class Logger { public function log($msg) { echo $msg; } } $util->setLogger(new Logger()); // php7+ $util->setLogger(new class { public function log($msg) { echo $msg; } });
Unicode codepoint 转译语法
这接受一个以16进制形式的 Unicode codepoint
,并打印出一个双引号或heredoc
包围的 UTF-8
编码格式的字符串。 可以接受任何有效的 codepoint
,并且开头的 0 是可以省略的
echo "\u{aa}";// ª echo "\u{0000aa}";// ª echo "\u{9999}";// 香
Closure::call
闭包绑定 简短干练的暂时绑定一个方法到对象上闭包并调用它。
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);
带过滤的unserialize
提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入
// 将所有的对象都转换为 __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]);
IntlChar类
这个类自身定义了许多静态方法用于操作多字符集的 unicode
字符。需要安装intl
拓展
printf('%x', IntlChar::CODEPOINT_MAX); echo IntlChar::charName('@'); var_dump(IntlChar::ispunct('!'));
预期
它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。以后可以使用这个这个进行断言测试
ini_set('assert.exception', 1); class CustomError extends AssertionError {} assert(false, new CustomError('Some error message'));
命名空间按组导入
从同一个命名空间下导入的类、函数、常量支持按组一次导入
#php7以前 use app\model\A; use app\model\B; #php7+ use app\model{A,B}
生成器支持返回表达式
它允许在生成器函数中通过使用 return
语法来返回一个表达式 (但是不允许返回引用值), 可以通过调用 Generator::getReturn()
方法来获取生成器的返回值, 但是这个方法只能在生成器完成产生工作以后调用一次。
$gen = (function() { yield 1; yield 2; return 3; })(); foreach ($gen as $val) { echo $val, PHP_EOL; } echo $gen->getReturn(), PHP_EOL; # output //1 //2 //3
生成器委派
现在,只需在最外层生成其中使用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; }
整数除法函数intdiv
var_dump(intdiv(10,3)) //3
会话选项设置
session_start()
可以加入一个数组覆盖php.ini
的配置
session_start([ 'cache_limiter' => 'private', 'read_and_close' => true, ]);
preg_replace_callback_array
可以使用一个关联数组来对每个正则表达式注册回调函数, 正则表达式本身作为关联数组的键, 而对应的回调函数就是关联数组的值
string preg_replace_callback_array(array $regexesAndCallbacks, string $input); $tokenStream = []; // [tokenName, lexeme] pairs $input = <<<'end' $a = 3; // variable initialisation end; // Pre PHP 7 code preg_replace_callback( [ '~\$[a-z_][a-z\d_]*~i', '~=~', '~[\d]+~', '~;~', '~//.*~' ], function ($match) use (&$tokenStream) { if (strpos($match[0], '$') === 0) { $tokenStream[] = ['T_VARIABLE', $match[0]]; } elseif (strpos($match[0], '=') === 0) { $tokenStream[] = ['T_ASSIGN', $match[0]]; } elseif (ctype_digit($match[0])) { $tokenStream[] = ['T_NUM', $match[0]]; } elseif (strpos($match[0], ';') === 0) { $tokenStream[] = ['T_TERMINATE_STMT', $match[0]]; } elseif (strpos($match[0], '//') === 0) { $tokenStream[] = ['T_COMMENT', $match[0]]; } }, $input ); // PHP 7+ code preg_replace_callback_array( [ '~\$[a-z_][a-z\d_]*~i' => function ($match) use (&$tokenStream) { $tokenStream[] = ['T_VARIABLE', $match[0]]; }, '~=~' => function ($match) use (&$tokenStream) { $tokenStream[] = ['T_ASSIGN', $match[0]]; }, '~[\d]+~' => function ($match) use (&$tokenStream) { $tokenStream[] = ['T_NUM', $match[0]]; }, '~;~' => function ($match) use (&$tokenStream) { $tokenStream[] = ['T_TERMINATE_STMT', $match[0]]; }, '~//.*~' => function ($match) use (&$tokenStream) { $tokenStream[] = ['T_COMMENT', $match[0]]; } ], $input );
随机数、随机字符函数
string random_bytes(int length); int random_int(int min, int max);
define 支持定义数组
#php7+ define('ALLOWED_IMAGE_EXTENSIONS', ['jpg', 'jpeg', 'gif', 'png']);
PHP7.0变化
错误和异常处理相关变更
PHP 7
改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为Error
异常抛出。
这也意味着,当发生错误的时候,以前代码中的一些错误处理的代码将无法被触发。 因为在 PHP 7
版本中,已经使用抛出异常的错误处理机制了。 (如果代码中没有捕获Error异常,那么会引发致命错误)。set_error_handle
不一定接收的是异常,有可能是错误。
ERROR
层级结构
interface Throwable |- Exception implements Throwable |- ... |- Error implements Throwable |- TypeError extends Error |- ParseError extends Error |- AssertionError extends Error |- ArithmeticError extends Error |- DivisionByZeroError extends ArithmeticError
function handler(Exception $e) { ... } set_exception_handler('handler'); // 兼容 PHP 5 和 7 function handler($e) { ... } // 仅支持 PHP 7 function handler(Throwable $e) { ... }
list
list
会按照原来的顺序进行赋值。不再是逆序了,且list
不再支持解开字符串
list($array[], $array[], $array[]) = [1, 2, 3]; var_dump($array); // [1, 2, 3]
foreach不再改变内部数组指针
<?php $array = [0, 1, 2]; foreach ($array as &$val) { var_dump(current($array)); } ?> #php 5 int(1) int(2) bool(false) #php7 int(0) int(0) int(0)
十六进制字符串不再被认为是数字
var_dump("0x123" == "291"); #php5 true #php7 false
$HTTP_RAW_POST_DATA 被移
$HTTP_RAW_POST_DATA
被移 使用php://input
代替
移除了 ASP 和 script PHP 标签
开标签 | 闭标签 |
<% | %> |
<%= | %> |