PHP 5-7:
1.改进的性能 - PHPNG代码合并在PHP7中,这是比 PHP5快两倍 - 待展开
2.降低内存消耗 - 优化后PHP7使用较少的资源 - 待展开
//PHP7使用新的 Zend Engine 3.0 提高应用程序性能两倍,比PHP5.6 低了 50% 的内存消耗。 它可以服务于更多的并发用户,无需任何额外的硬件。 /** 在执行的Magento事务相比PHP5.6,PHP7要快两倍 在执行 Drupal 事务相比PHP5.6,PHP7证明快两倍 PHP7 证明自己比 PHP5.6 快两倍,因为在执行 WordPress 事务相比 */
3.标量类型声明 - 现在,参数和返回值类型可以被强制执行(强类型语言)
/** 支持(string,int,float,bool,interfaces,array,callable,类名) - 7.1新增 Nullable,void,iterable(与callable类似,实现了Traversavle接口的对象) - 7.2新增 object(可用于逆变(contravariant)参数输入和协变(covariant)返回任何对象类型) - 7.4支持在类的属性中添加指定类型。 ps: 不支持别名,例如boolean,integer。 callable可理解为可被调用的函数。(可用is_callable()验证,相对的有callback的概念。) */
// Coercive mode 强制模式 (默认) function sumOfInts(int ...$ints) //标量类型声明 int型 { return array_sum($ints); } var_dump(sumOfInts(2, '3', 4.1)); //int(9)
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)
declare (strict_types = 1); //开启严格模式,检查参数的类型,不一致会报错
//可为空(Nullable)类型(PHP7.1) //参数以及返回值的类型现在可以通过在类型前加上一个问号使之允许为空。 function testReturn(): ?string {}
//Void 函数(PHP7.1) //一个新的返回值类型void被引入。 返回值声明为 void 类型的方法要么干脆省去 return 语句,要么使用一个空的 return 语句。 对于 void 函数来说,null 不是一个合法的返回值。 function swap(&$left, &$right) : void {}
//7.4 有限返回类型协变与参数类型逆变 继承关系 class A {} class B extends A {} class Producer { public function method(): A {} } class ChildProducer extends Producer { public function method(): B {} }
4.一致性的64位支持 - 64位架构机器持续支持
phpinfo(); //Architecture //32 位 PHP 是 4Bytes,而 64位 PHP 是 8Bytes if (PHP_INT_SIZE == 4) { $bit = 32; } else { $bit = 64; }
5.1.改进异常层次结构 - 异常层次结构得到改善;
PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error 异常抛出。
这种 Error 异常可以像 Exception 异常一样被第一个匹配的 try / catch 块所捕获。如果没有匹配的 catch 块,则调用异常处理函数(事先通过 set_exception_handler() 注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。
Error 类并非继承自 Exception 类,所以不能用 catch (Exception e)...来捕获Error。你可以用catch(Errore) { … },或者通过注册异常处理函数( set_exception_handler())来捕获 Error。
/** 异常层次结构 Throwable Error ArithmeticError DivisionByZeroError AssertionError ParseError TypeError Exception */
5.2.许多致命错误转换成异常 - 异常的范围增大覆盖为许多致命的错误转化异常
(5,6)php5.6.x到PHP7.0.x 不向后兼容的变更
<?php //set_exception_handler() 不再保证收到的一定是 Exception 对象 // PHP 5 时代的代码将会出现问题 function handler(Exception $e) { ... } set_exception_handler('handler'); // 兼容 PHP 5 和 7 function handler($e) { ... } // 仅支持 PHP 7 function handler(Throwable $e) { ... } ?>
//E_STRICT 警告级别变更
场景 | 新的级别/行为 |
---|---|
抽象静态方法 | 不再警告,会引发错误 |
重复定义构造器函数 | 不再警告,会引发错误 |
在继承的时候,方法签名不匹配 | E_WARNING |
在两个 trait 中包含相同的(兼容的)属性 | 不再警告,会引发错误 |
以非静态调用的方式访问静态属性 | E_NOTICE |
变量应该以引用的方式赋值 | E_NOTICE |
变量应该以引用的方式传递 | E_NOTICE |
以静态方式调用实例方法 | E_DEPRECATED |
6.已过时的API和扩展删除 - 不同的旧的和不支持的应用程序和扩展,从最新的版本中删除
/** call_user_method(),call)_user_method_array() 所有ereg*函数 mcrypt别名 所有ext/mysql函数 intl别名 ...... */
/** always_populate_raw_post_data asp_tags */
7.数组,循环等处理改变
/** 修复list()倒序赋值(仅影响数组) 修复数组的生成顺序 函数参数附近的括号不再影响行为(一些不允许的函数嵌套行为,5里可以用()处理,7修复了) 修复foreach更改内部指针的问题 foreach 通过值遍历时,操作的值为数组的副本(无&,对$arr的修改,不会在使用$v时触发,例如unset($arr[0])后,$arr[0]代表的那个$v仍能被正常使用 ? 5是否也这样待测试) foreach通过引用遍历时,有更好的迭代特性(在迭代中能更好的跟踪变化) */
//修复list()倒序赋值(仅影响数组) list($a[], $a[], $a[]) = [1, 2, 3]; var_dump($a); //5 => 3,2,1 //7 => 1,2,3
//修复数组的生成顺序 $array = []; $array["a"] =& $array["b"]; $array["b"] = 1; var_dump($array); //5 => ["b"=>&int(1),"a"=>&int(1)] //7 => ["a"=>&int(1),"b"=>&int(1)]
//函数参数附近的括号不再影响行为(一些不允许的函数嵌套行为,5里可以用()处理,7修复了) function getArray() { return [1, 2, 3]; } function squareArray(array &$a) { foreach ($a as &$v) { $v **= 2; } } // Generates a warning in PHP 7. squareArray((getArray()));
//修复foreach更改内部指针的问题 $array = [0, 1, 2]; foreach ($array as &$val) { var_dump(current($array)); } //5 => 1,2,false //7 => 0,0,0
//foreach通过引用遍历时,有更好的迭代特性(在迭代中能更好的跟踪变化) $array = [0]; foreach ($array as &$val) { var_dump($val); $array[1] = 1; } //5 => 0 //7 => 0,1
8.整形,字符串处理改变
/** 无效的8进制字符,现在会报错(8进制字符的无效数字,之前会被自动删节) 负位移运算,现在会报错 超范围后位移。之前会溢出(原文:这一操作是结构依赖的),现在会始终得到0。 除以0的变化 */
//除以0的变化 //除法运算符 (/) 会返回一个由 IEEE 754 指定的浮点数:+INF, -INF 或 NAN。取模操作符 (%) 则会抛出一个 DivisionByZeroError 异常,并且不再产生 E_WARNING 错误 var_dump(3/0); var_dump(0/0); var_dump(0%0); //5 => false,false,false(三个warning) //7 => float(INF),float(NAN),Fatal error(前两个是warning)
/** 含十六进制字符串不再被认为是数字(filter_var() 函数可以用于检查一个 string 是否含有十六进制数字,并将其转换为integer。返回值为false或int) 支持unicode输出了,同时也导致对应字符串要慎用 - '\u{'。 */
//unicode输出 echo '\u{UNICODE_CODE}'; //输出对应的unicode字符
9.语法糖
//<=> (太空船操作符|组合比较符) $a <=> $b; // <:-1,=:0,>:1
//?? (null合并运算符) // 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';
//通过define定义常量数组(在 PHP5.6 中仅能通过 const 定义) define('ANIMALS', [ 'dog', 'cat', 'bird' ]); echo ANIMALS[1]; // 输出 "cat"
//use语句 // Before PHP 7 use com\web3\ClassA; use com\web3\ClassB; use com\web3\ClassC as C; use function com\web3\fn_a; use function com\web3\fn_b; use function com\web3\fn_c; use const com\web3\ConstA; use const com\web3\ConstB; use const com\web3\ConstC; // PHP 7+ code use com\web3\{ClassA, ClassB, ClassC as C}; use function com\web3\{fn_a, fn_b, fn_c}; use const com\web3\{ConstA, ConstB, ConstC};
//7.1 //短数组语法([])现在作为list()语法的一个备选项,可以用于将数组的值赋给一些变量(包括在foreach中)。 $data = [ [1, 'Tom'], [2, 'Fred'], ]; // list() style list($id1, $name1) = $data[0]; // [] style [$id1, $name1] = $data[0]; // list() style foreach ($data as list($id, $name)) { // logic here with $id and $name } // [] style foreach ($data as [$id, $name]) { // logic here with $id and $name } //list()现在支持键名 === 短数组语法也支持 $data = [ ["id" => 1, "name" => 'Tom'], ["id" => 2, "name" => 'Fred'], ]; // list() style list("id" => $id1, "name" => $name1) = $data[0]; // [] style ["id" => $id1, "name" => $name1] = $data[0]; // list() style foreach ($data as list("id" => $id, "name" => $name)) { // logic here with $id and $name } // [] style foreach ($data as ["id" => $id, "name" => $name]) { // logic here with $id and $name }
//7.1 多异常捕获 try { // some code } catch (FirstException | SecondException $e) { // handle first and second exceptions }
//7.1 支持为负的字符串偏移量 //现在所有支持偏移量的字符串操作函数 都支持接受负数作为偏移量,包括通过[]或{}操作字符串下标。在这种情况下,一个负数的偏移量会被理解为一个从字符串结尾开始的偏移量。 var_dump("abcdef"[-2]); //e var_dump(strpos("aabbcc", "b", -3)); //3 从第二个d start开始查找
//7.2 通过名称加载扩展 //扩展文件不再需要通过文件加载 (Unix下以.so为文件扩展名,在Windows下以 .dll 为文件扩展名) 进行指定。可以在php.ini配置文件进行启用, 也可以使用 dl() 函数进行启用。
//7.4 空合并运算赋值符 $array['key'] ??= computeDefault(); // 等同于以下旧写法 if (!isset($array['key'])) { $array['key'] = computeDefault(); }
//7.4 数组展开操作 $parts = ['apple', 'pear']; $fruits = ['banana', 'orange', ...$parts, 'watermelon']; // ['banana', 'orange', 'apple', 'pear', 'watermelon'];
//7.4 数值文字分隔符 //数字文字可以在数字之间包含下划线。 6.674_083e-11; // float 299_792_458; // decimal 0xCAFE_F00D; // hexadecimal 0b0101_1111; // binary
//7.4 箭头函数 //提供了一种更简洁的定义函数的方法。 $factor = 10; $nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]); // $nums = array(10, 20, 30, 40); //箭头函数,相比匿名函数,可不使用use,直接获取其他参数。 function () use () {} //箭头函数中所有使用的参数为副本,不会影响其本身
10.其他特性
/** 1.匿名类 2.Closure::call()(Closure::call() 方法加入到临时绑定(bindTo)的对象范围,以简便方式封闭和调用它 它相比绑定到PHP5.6性能更快) 3.过滤unserialize() 4.国际字符(新的 IntlChar 类添加其目的是公开更多的ICU功能。 这个类定义了许多可用于操纵Unicode字符的静态方法和常数。你需要在使用这个类之前安装 Intl 扩展) 5.CSPRNG 6.期望(断言)(期望是向后兼容的增强到旧 assert() 函数。期望允许在生产代码零成本的断言,并提供在断言失败时抛出自定义异常的能力。assert() 不是一种语言构建体,其中第一个参数是一个表达式的比较字符串或布尔用于测试。) 7.整数除法 8.Session选项 9.生成器 10.类常量可见性(7.1) 现在起支持设置类常量的可见性(面向对象相关) - visibility,即public,private,protected 11.允许重写抽象方法(Abstract method)(7.2) - 当一个抽象类继承于另外一个抽象类的时候,继承后的抽象类可以重写被继承的抽象类的抽象方法 */
//匿名类(现在支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。) 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());
//Closure::call() //before7 <?php class A { private $x = 1; } // Define a closure Pre PHP 7 code $getValue = function() { return $this->x; }; // Bind a clousure $value = $getValue->bindTo(new A, 'A'); print($value()); //1 ?>
7+ <?php class A { private $x = 1; } // PHP 7+ code, Define $value = function() { return $this->x; }; print($value->call(new A)); //1 ?>
//为unserialize()提供过滤(这个特性旨在提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入。) //说明: 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]); //别处找的例子 class MyClass1 { public $obj1prop; } class MyClass2 { public $obj2prop; } $obj1 = new MyClass1(); $obj1->obj1prop = 1; $obj2 = new MyClass2(); $obj2->obj2prop = 2; $serializedObj1 = serialize($obj1); $serializedObj2 = serialize($obj2); // default behaviour that accepts all classes // second argument can be ommited. // if allowed_classes is passed as false, unserialize converts all objects into __PHP_Incomplete_Class object $data = unserialize($serializedObj1 , ["allowed_classes" => true]); // converts all objects into __PHP_Incomplete_Class object except those of MyClass1 and MyClass2 $data2 = unserialize($serializedObj2 , ["allowed_classes" => ["MyClass1", "MyClass2"]]); print($data->obj1prop); print("<br/>"); print($data2->obj2prop); //输出: 1,2
//国际字符 rintf('%x', IntlChar::CODEPOINT_MAX); //10ffff print (IntlChar::charName('@')); //COMMERCIAL AT print(IntlChar::ispunct('!')); //true
php5,原有的随机数为非加密安全伪随机数。 PHP中的随机数安全问题 - 知乎
//CSPRNG 在PHP7,以下两个新的函数引入以产生一个跨平台的方式加密安全整数和字符串。 random_bytes(); //生成加密安全伪随机字节。适合于使用来生成密码,密码学随机的任意长度的字符串。 random_int(); //生成加密安全伪随机整数。适合于用于结果是非常重要的加密随机整数。
断言,assert,php测试相关。 断言
//整数除法 $value = intdiv(10,3); var_dump($value); print(" "); print($value);
//从PHP7+,session_start()函数接受数组参数覆盖在php.ini中设置的会话配置指令。这些选项支持 session.lazy,在默认情况下如果PHP会话数据改变,那么会覆盖任何会话数据信息。 //添加另一种选择是:read_and_close,这表明会话数据应被读取,然后该会话应当立即被关闭不变。例如,session.cache_limiter 设置为私有,并设置标志使用下面的代码片段之后立即关闭会话。 session_start([ 'cache_limiter' => 'private', 'read_and_close' => true, ]);
//生成器 //在PHP5.5引入生成器的概念。生成器函数每执行一次就得到一个yield标识的值。在PHP7中,当生成器迭代完成后,可以获取该生成器函数的返回值。通过Generator::getReturn()得到 function generator() { yield 1; yield 2; yield 3; return "a"; } $generatorClass = ("generator")(); foreach ($generatorClass as $val) { echo $val ." "; } echo $generatorClass->getReturn(); //1 2 3 a //在生成器中可以引入另一个或几个生成器,只需要写yield from functionName1 function generator1() { yield 1; yield 2; yield from generator2(); yield from generator3(); } function generator2() { yield 3; yield 4; } function generator3() { yield 5; yield 6; } foreach (generator1() as $val) { echo $val, " "; }
curl,http2,套接字,ticks,异步etc
1.debug_zval_dump() 现在打印 “int” 替代 “long”, 打印 “float” 替代 “double”
2.dirname() 增加了可选的第二个参数, depth, 获取当前目录向上 depth 级父目录的名称。
3.getrusage() 现在支持 Windows.mktime() and gmmktime() 函数不再接受 is_dst 参数。
4.preg_replace() 函数不再支持 “\e” (PREG_REPLACE_EVAL). 应当使用 preg_replace_callback() 替代。
5.setlocale() 函数不再接受 category 传入字符串。 应当使用 LC_* 常量。
6.exec(), system() and passthru() 函数对 NULL 增加了保护.
7.shmop_open() 现在返回一个资源而非一个int, 这个资源可以传给shmop_size(), shmop_write(), shmop_read(), shmop_close() 和 shmop_delete().
8.为了避免内存泄露,xml_set_object() 现在在执行结束时需要手动清除 $parse。
9.curl_setopt 设置项CURLOPT_SAFE_UPLOAD变更
TRUE 禁用 @ 前缀在 CURLOPT_POSTFIELDS 中发送文件。 意味着 @ 可以在字段中安全得使用了。 可使用 CURLFile作为上传的代替。
PHP 5.5.0 中添加,默认值 FALSE。 PHP 5.6.0 改默认值为 TRUE。. PHP 7 删除了此选项, 必须使用 CURLFile interface 来上传文件。
1.开启Opcache
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
2.使用GCC 4.8以上进行编译
只有GCC 4.8以上PHP才会开启Global Register for opline and execute_data支持, 这个会带来5%左右的性能提升(Wordpres的QPS角度衡量)
3.开启HugePage (根据系统内存决定)
4.PGO (Profile Guided Optimization)
第一次编译成功后,用项目代码去训练PHP,会产生一些profile信息,最后根据这些信息第二次gcc编译PHP就可以得到量身定做的PHP7