# php更新内容
[php4变化日志](https://www.php.net/ChangeLog-4.php)(主要是修复bug方面)
[php5变化日志](http://php.net/ChangeLog-5.php) (主要是修复bug方面)
[php7变化日志](http://php.net/ChangeLog-7.php)(主要是修复bug方面)
[更新日志](https://www.php.net/manual/zh/doc.changelog.php)(绑定的扩展的函数更新内容)
[迁移日志(包含新增或废弃的特性和函数等)](https://www.php.net/manual/zh/appendices.php)
主要新特性一览,详情查看迁移日志
# **php5.4新特性**
## **增加短数组支持如:\[1, 2, 3, 4\]**
## **新增Trait**
# **php5.5新特性**
## **新增yield关键字简化生成器**
**新增密码加密及验证**
```
<pre class="calibre10">```
<span class="token">//之前</span>
<span class="token">//模拟input提交的密码</span>
$user_input <span class="token1">=</span> <span class="token2">'12+#æ345'</span><span class="token3">;</span>
<span class="token">//crypt()函数不能正确处理加号。请首先对密码使用urlencode,以确保登录过程可以处理任何字符</span>
$pass <span class="token1">=</span> <span class="token4">urlencode</span><span class="token3">(</span>$user_input<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
$pass_crypt <span class="token1">=</span> <span class="token4">crypt</span><span class="token3">(</span>$pass<span class="token3">)</span><span class="token3">;</span>
<span class="token5">if</span> <span class="token3">(</span>$pass_crypt <span class="token1">==</span> <span class="token4">crypt</span><span class="token3">(</span>$pass<span class="token3">,</span> $pass_crypt<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
echo <span class="token2">"成功!有效的密码"</span><span class="token3">;</span>
<span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span>
echo <span class="token2">"无效的密码"</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">//当校验密码时,应该使用一个不容易被时间攻击的字符串比较函数来比较crypt()的输出与之前已知的哈希。出于这个目的,PHP5.6开始提供了hash_equals()</span>
$hashed_password <span class="token1">=</span> <span class="token4">crypt</span><span class="token3">(</span><span class="token2">'mypassword'</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 自动生成盐值</span>
<span class="token">/* 你应当使用 crypt() 得到的完整结果作为盐值进行密码校验,以此来避免使用不同散列算法导致的问题。(如上所述,基于标准 DES 算法的密码散列使用 2 字符盐值,但是基于 MD5 算法的散列使用 12 个字符盐值。)*/</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">hash_equals</span><span class="token3">(</span>$hashed_password<span class="token3">,</span> <span class="token4">crypt</span><span class="token3">(</span>$user_input<span class="token3">,</span> $hashed_password<span class="token3">)</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
echo <span class="token2">"Password verified!"</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">//新特性</span>
<span class="token">/**
* 我们想要使用默认算法散列密码
* 当前是 BCRYPT,并会产生 60 个字符的结果。
*
* 请注意,随时间推移,默认算法可能会有变化,
* 所以需要储存的空间能够超过 60 字(255字不错)
* 强烈建议不要自己为这个函数生成盐值(salt)。只要不设置,它会自动创建安全的盐值
* password_hash 参数2有三个加密算法:PASSWORD_DEFAULT(默认),PASSWORD_BCRYPT ,PASSWORD_ARGON2I(php7.2加入)
*/</span>
$hash<span class="token1">=</span><span class="token4">password_hash</span><span class="token3">(</span><span class="token2">"rasmuslerdorf"</span><span class="token3">,</span> PASSWORD_DEFAULT<span class="token3">)</span><span class="token3">;</span><span class="token">//$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">password_verify</span><span class="token3">(</span><span class="token2">'rasmuslerdorf'</span><span class="token3">,</span> $hash<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
echo <span class="token2">'Password is valid!'</span><span class="token3">;</span>
<span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span>
echo <span class="token2">'Invalid password.'</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">print_r</span><span class="token3">(</span>password_get_info <span class="token3">(</span>$hash<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//Array ( [algo] => 1 [algoName] => bcrypt [options] => Array ( [cost] => 10 ) )</span>
```
```

password\_hash方法我们无需关注salt,只需要将password\_hash返回的hash保存在数据库就ok
```
<pre class="calibre10">```
$_POST<span class="token3">[</span><span class="token2">'pwd'</span><span class="token3">]</span><span class="token1">==</span> <span class="token2">'rasmuslerdorf'</span><span class="token3">;</span>
$password <span class="token1">=</span>$_POST<span class="token3">[</span><span class="token2">'pwd'</span><span class="token3">]</span><span class="token3">;</span>
<span class="token">//数据库没有就使用password_hash,数据库有则查查出数据库的hash</span>
<span class="token5">if</span><span class="token3">(</span><span class="token1">!</span><span class="token4">empty</span><span class="token3">(</span>$res<span class="token1">=</span><span class="token4">findPwdToMysql</span><span class="token3">(</span>$_POST<span class="token3">[</span><span class="token2">'user'</span><span class="token3">]</span><span class="token3">,</span> $_POST<span class="token3">[</span><span class="token2">'pwd'</span><span class="token3">]</span><span class="token3">)</span><span class="token3">)</span><span class="token3">)</span><span class="token3">{</span>
$hash<span class="token1">=</span>$res<span class="token3">;</span>
<span class="token3">}</span><span class="token5">else</span><span class="token3">{</span>
$hash<span class="token1">=</span><span class="token4">password_hash</span><span class="token3">(</span>$password<span class="token3">)</span><span class="token3">;</span><span class="token">//$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS</span>
<span class="token4">savePwdTosql</span><span class="token3">(</span>$hash<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">// 当硬件性能得到改善时,cost 参数可以再修改(默认10)</span>
$options <span class="token1">=</span> <span class="token4">array</span><span class="token3">(</span><span class="token2">'cost'</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">11</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">// 根据明文密码验证储存的散列</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">password_verify</span><span class="token3">(</span>$password<span class="token3">,</span> $hash<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token">// 检测是否有更新的可用散列算法</span>
<span class="token">// 或者 cost 发生变化</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">password_needs_rehash</span><span class="token3">(</span>$hash<span class="token3">,</span> PASSWORD_DEFAULT<span class="token3">,</span> $options<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token">// 如果是这样,则创建新散列,替换旧散列</span>
$newHash <span class="token1">=</span> <span class="token4">password_hash</span><span class="token3">(</span>$password<span class="token3">,</span> PASSWORD_DEFAULT<span class="token3">,</span> $options<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">// 使用户登录setcookie()</span>
<span class="token3">}</span>
```
```
**访问单个元素和字符**
```
<pre class="calibre10">```
<span class="token">//之前</span>
$arr<span class="token1">=</span><span class="token3">[</span><span class="token6">123</span><span class="token3">]</span><span class="token3">;</span>
$str<span class="token1">=</span><span class="token2">'abc'</span><span class="token3">;</span>
$arr<span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">;</span>
$str<span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">;</span>
<span class="token">//新特性:</span>
<span class="token3">[</span><span class="token6">123</span><span class="token3">]</span><span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">;</span>
<span class="token2">'abc'</span><span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">;</span>
```
```
foreach控制结构现在支持通过[list()](https://www.php.net/manual/zh/function.list.php)构造将嵌套数组分离到单独的变量
```
<pre class="calibre10">```
<span class="token">//之前</span>
$arr1<span class="token1">=</span><span class="token3">[</span><span class="token6">1</span><span class="token3">,</span><span class="token6">2</span><span class="token3">]</span><span class="token3">;</span>
$arr2<span class="token1">=</span><span class="token3">[</span><span class="token6">3</span><span class="token3">,</span><span class="token6">4</span><span class="token3">]</span><span class="token3">;</span>
list <span class="token3">(</span>$a<span class="token3">,</span> $b<span class="token3">)</span><span class="token1">=</span>$arr1<span class="token3">;</span>
list <span class="token3">(</span>$a<span class="token3">,</span> $b<span class="token3">)</span><span class="token1">=</span>$arr2<span class="token3">;</span>
<span class="token">//新特性:</span>
$array <span class="token1">=</span> <span class="token3">[</span>
<span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">]</span><span class="token3">,</span>
<span class="token3">[</span><span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">]</span><span class="token3">,</span>
<span class="token3">]</span><span class="token3">;</span>
foreach <span class="token3">(</span>$array as <span class="token4">list</span><span class="token3">(</span>$a<span class="token3">,</span> $b<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
echo <span class="token2">"A: $a; B: $b\n"</span><span class="token3">;</span>
<span class="token3">}</span>
输出:
A<span class="token3">:</span> <span class="token6">1</span><span class="token3">;</span> B<span class="token3">:</span> <span class="token6">2</span>
A<span class="token3">:</span> <span class="token6">3</span><span class="token3">;</span> B<span class="token3">:</span> <span class="token6">4</span>
```
```
## **异常处理新增finally块,`try{}catch{}finally{}`**
finally块中的代码总是在try和catch块之后执行,不管是否抛出了异常,也不管正常的执行是否继续
# **php5.6 新特性**
## **可变数量的参数**
可变参数由 ... 语法实现;在 PHP 5.5 及更早版本中,使用函数 func\_num\_args(),func\_get\_arg(),和 func\_get\_args()
```
<pre class="calibre10">```
<span class="token">//5.6以前实现可变参数</span>
<span class="token5">function</span> <span class="token4">sum</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>
$acc <span class="token1">=</span> <span class="token6">0</span><span class="token3">;</span>
foreach <span class="token3">(</span><span class="token4">func_get_args</span><span class="token3">(</span><span class="token3">)</span> as $n<span class="token3">)</span> <span class="token3">{</span>
$acc <span class="token1">+</span><span class="token1">=</span> $n<span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">return</span> $acc<span class="token3">;</span>
<span class="token3">}</span>
echo <span class="token4">sum</span><span class="token3">(</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//新特性</span>
<span class="token5">function</span> <span class="token4">f</span><span class="token3">(</span>$req<span class="token3">,</span> $opt <span class="token1">=</span> <span class="token5">null</span><span class="token3">,</span> <span class="token3">.</span><span class="token3">.</span><span class="token3">.</span>$params<span class="token3">)</span> <span class="token3">{</span>
<span class="token">// $params 是一个包含了剩余参数的数组</span>
<span class="token4">printf</span><span class="token3">(</span><span class="token2">'$req的值: %d; $opt的值: %d; $params的个数: %d;'</span><span class="token3">,</span> $req<span class="token3">,</span> $opt<span class="token3">,</span> <span class="token4">count</span><span class="token3">(</span>$params<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
echo <span class="token4">gettype</span><span class="token3">(</span>$params<span class="token3">)</span><span class="token3">.</span><span class="token2">"<br>"</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">f</span><span class="token3">(</span><span class="token6">1</span><span class="token3">)</span><span class="token3">;</span><span class="token">//$req的值: 1; $opt的值: 0; $params的个数: 0;array</span>
<span class="token4">f</span><span class="token3">(</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">)</span><span class="token3">;</span><span class="token">//$req的值: 1; $opt的值: 2; $params的个数: 0;array</span>
<span class="token4">f</span><span class="token3">(</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">)</span><span class="token3">;</span><span class="token">//$req的值: 1; $opt的值: 2; $params的个数: 1;array</span>
<span class="token4">f</span><span class="token3">(</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">)</span><span class="token3">;</span><span class="token">//$req的值: 1; $opt的值: 2; $params的个数: 2;array</span>
<span class="token4">f</span><span class="token3">(</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">,</span> <span class="token6">5</span><span class="token3">)</span><span class="token3">;</span><span class="token">//$req的值: 1; $opt的值: 2; $params的个数: 3;array</span>
```
```
在调用函数的时候,使用...运算符, 将**数组**和**可遍历**对象展开为函数参数。 在其他编程语言,比如 Ruby中,这被称为连接运算符
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">add</span><span class="token3">(</span>$a<span class="token3">,</span> $b<span class="token3">,</span> $c<span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> $a <span class="token1">+</span> $b <span class="token1">+</span> $c<span class="token3">;</span>
<span class="token3">}</span>
<span class="token">//add(1,...[2, 3])</span>
$operators <span class="token1">=</span> <span class="token3">[</span><span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">]</span><span class="token3">;</span>
echo <span class="token4">add</span><span class="token3">(</span><span class="token6">1</span><span class="token3">,</span> <span class="token3">.</span><span class="token3">.</span><span class="token3">.</span>$operators<span class="token3">)</span><span class="token3">;</span><span class="token">//6 与add(1,2,3)效果一样</span>
```
```
## **使用表达式定义常量**
```
<pre class="calibre10">```
<span class="token">//之前只能使用静态值定义常量</span>
const ONE <span class="token1">=</span> <span class="token6">1</span><span class="token3">;</span>
<span class="token">//现在可以用表达式定义常量</span>
const TWO <span class="token1">=</span> ONE <span class="token1">*</span> <span class="token6">2</span><span class="token3">;</span>
```
```
## **新增幂运算**
加入右连接运算符\*\*\**来进行幂运算。 同时还支持简写的*\*\*=\*运算符,表示进行幂运算并赋值
```
<pre class="calibre10">```
<span class="token4">printf</span><span class="token3">(</span><span class="token2">"2的3次方等于 %d\n"</span><span class="token3">,</span> <span class="token6">2</span> <span class="token1">*</span><span class="token1">*</span> <span class="token6">3</span><span class="token3">)</span><span class="token3">;</span><span class="token">//2的3次方等于 8</span>
```
```
## **新增\_\_debugInfo()魔术方法 当使用vardump打印类对象时触发**
## **扩展了use 以前可以导入命名空间的类现在还可以导入函数及常量**
```
<pre class="calibre10">```
namespace Name\Space <span class="token3">{</span>
const FOO <span class="token1">=</span> <span class="token6">42</span><span class="token3">;</span>
<span class="token5">function</span> <span class="token4">f</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo __FUNCTION__<span class="token3">.</span><span class="token2">"\n"</span><span class="token3">;</span> <span class="token3">}</span>
<span class="token3">}</span>
namespace <span class="token3">{</span>
use const Name\Space\FOO<span class="token3">;</span>
use <span class="token5">function</span> Name\Space\f<span class="token3">;</span>
echo FOO<span class="token3">.</span><span class="token2">"\n"</span><span class="token3">;</span><span class="token">//42</span>
<span class="token4">f</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//Name\Space\f</span>
<span class="token3">}</span>
```
```
# **php7新特性**
php7有三种方式创建空对象
```
<pre class="calibre10">```
$obj1 <span class="token1">=</span> <span class="token5">new</span> <span class="token4"><span class="token3">\</span>stdClass</span><span class="token3">;</span> <span class="token">// Instantiate stdClass object</span>
$obj2 <span class="token1">=</span> <span class="token5">new</span> <span class="token4">class</span><span class="token3">{</span><span class="token3">}</span><span class="token3">;</span> <span class="token">// Instantiate anonymous class</span>
$obj3 <span class="token1">=</span> <span class="token3">(</span>object<span class="token3">)</span><span class="token3">[</span><span class="token3">]</span><span class="token3">;</span> <span class="token">// Cast empty array to object</span>
<span class="token4">var_dump</span><span class="token3">(</span>$obj1<span class="token3">)</span><span class="token3">;</span> <span class="token">// object(stdClass)#1 (0) {}</span>
<span class="token4">var_dump</span><span class="token3">(</span>$obj2<span class="token3">)</span><span class="token3">;</span> <span class="token">// object(class@anonymous)#2 (0) {}</span>
<span class="token4">var_dump</span><span class="token3">(</span>$obj3<span class="token3">)</span><span class="token3">;</span> <span class="token">// object(stdClass)#3 (0) {}</span>
```
```
$obj1和$obj3类型一样但是不相等
## **1.在use语句增加了group支持**
```
<pre class="calibre10">```
use FooLibrary\Bar\Baz\<span class="token3">{</span> ClassA<span class="token3">,</span> ClassB<span class="token3">,</span> ClassC<span class="token3">,</span> ClassD as Fizbo <span class="token3">}</span><span class="token3">;</span>
```
```
php7.2末尾可以留,而不会报错
```
<pre class="calibre10">```
use FooLibrary\Bar\Baz\<span class="token3">{</span> ClassA<span class="token3">,</span> ClassB<span class="token3">,</span> ClassC<span class="token3">,</span> ClassD as Fizbo<span class="token3">,</span> <span class="token3">}</span><span class="token3">;</span>
```
```
## **2.类型约束与标量类型声明(标量string、int、float和 bool)**
现在可在参数前加上参数类型,支持:具体类名接口名(php5.0),self(php5.0),array(php5.1),callable(php5.4),string(php7.0),int(php7.0),float(php7.0),bool(php7.0),iterable(php7.1),object(php7.2)
> 特别注意 Closure类型约束的是匿名函数,匿名函数本身就是个Closure对象
> php有两种模式强制模式(默认)和严格模式
> 声明严格模式`declare(strict_types=1);`后,如果形参声明为int那么参数是其他类型比如string时就会抛出致命错误,强制模式下的话会将string转换为int而不会报错
> 由上可知php5有可以约束array 类和接口 可调用函数 self 类型,我们可以简单的认为php5类型约束是严格模式如`function foo(array $arr) {} foo(null)`会报错提示给的参数不是指定的类型,但是参数为null时还是会报这个错,解决办法是将默认参数给个null`function foo(array $arr = null) {}`这样fool(null)就不会报错了
```
<pre class="calibre10">```
class <span class="token4">A</span><span class="token3">{</span>
public $name<span class="token1">=</span><span class="token5">null</span><span class="token3">;</span>
public <span class="token5">function</span> <span class="token4">demo</span><span class="token3">(</span>self $a<span class="token3">)</span><span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$a<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span>
$this<span class="token1">-</span><span class="token1">></span><span class="token4">demo</span><span class="token3">(</span>$this<span class="token3">)</span><span class="token3">;</span>
<span class="token">//$this->demo(new stdClass()); // 致命错误 A::demo() must be an instance of A</span>
<span class="token3">}</span>
<span class="token3">}</span>
class <span class="token4">B</span> implements <span class="token4">Iterator</span><span class="token3">{</span><span class="token">//Iterator继承Traversable</span>
public <span class="token5">function</span> current <span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token">//返回当前产生的值</span>
public <span class="token5">function</span> key <span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token">//返回当前产生的键</span>
public <span class="token5">function</span> next <span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token">// 生成器继续执行</span>
public <span class="token5">function</span> rewind <span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token">//重置迭代器</span>
public <span class="token5">function</span> valid <span class="token3">(</span><span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token">//检查迭代器是否被关闭</span>
<span class="token3">}</span>
<span class="token5">new</span> <span class="token4">A</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//字符串</span>
<span class="token5">function</span> <span class="token4">demo</span><span class="token3">(</span>string $param<span class="token3">)</span><span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_string</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo</span><span class="token3">(</span><span class="token6">1</span><span class="token3">)</span><span class="token3">;</span><span class="token">//true</span>
<span class="token4">demo</span><span class="token3">(</span><span class="token6">2.2</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//true</span>
<span class="token">//整数</span>
<span class="token5">function</span> <span class="token4">demo1</span><span class="token3">(</span>int $param<span class="token3">)</span><span class="token3">{</span>
echo $param<span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_integer</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo1</span><span class="token3">(</span><span class="token2">'1.1'</span><span class="token3">)</span><span class="token3">;</span><span class="token">//1 true</span>
<span class="token4">demo1</span><span class="token3">(</span><span class="token6">1.1</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//1 true</span>
<span class="token">//浮点数</span>
<span class="token5">function</span> <span class="token4">demo2</span><span class="token3">(</span>float $param<span class="token3">)</span><span class="token3">{</span>
echo $param<span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_float</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo2</span><span class="token3">(</span><span class="token2">'1.2'</span><span class="token3">)</span><span class="token3">;</span><span class="token">//1.2 true</span>
<span class="token4">demo2</span><span class="token3">(</span><span class="token6">1</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//1 true</span>
<span class="token">//布尔值</span>
<span class="token5">function</span> <span class="token4">demo3</span><span class="token3">(</span>bool $param<span class="token3">)</span><span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_bool</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo3</span><span class="token3">(</span><span class="token2">'a'</span><span class="token3">)</span><span class="token3">;</span><span class="token">// true true</span>
<span class="token4">demo3</span><span class="token3">(</span><span class="token6">3.3</span><span class="token3">)</span><span class="token3">;</span><span class="token">// true true</span>
<span class="token">//数组</span>
<span class="token5">function</span> <span class="token4">demo4</span><span class="token3">(</span>array $param<span class="token3">)</span><span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_array</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo4</span><span class="token3">(</span><span class="token3">[</span><span class="token2">'a'</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span><span class="token">//['a'] true</span>
<span class="token">//demo4('a');//demo4() must be of the type array</span>
<span class="token">//函数</span>
<span class="token5">function</span> <span class="token4">demo5</span><span class="token3">(</span>callable $param<span class="token3">)</span><span class="token3">{</span>
$<span class="token4">param</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_callable</span><span class="token3">(</span>$param<span class="token3">,</span><span class="token6">true</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo5</span><span class="token3">(</span><span class="token5">function</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span>echo <span class="token6">111</span><span class="token3">;</span><span class="token3">}</span><span class="token3">)</span><span class="token3">;</span><span class="token">// 111 true</span>
<span class="token">//对象</span>
<span class="token5">function</span> <span class="token4">demo6</span><span class="token3">(</span>object $param<span class="token3">)</span><span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">is_object</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo6</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">A</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//true</span>
<span class="token">//迭代对象</span>
<span class="token5">function</span> <span class="token4">demo7</span><span class="token3">(</span>iterable $param<span class="token3">)</span><span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$param <span class="token5">instanceof</span> <span class="token4">Traversable</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//var_dump(is_iterable($param));</span>
<span class="token3">}</span>
<span class="token4">demo7</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">B</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//true</span>
<span class="token4">demo7</span><span class="token3">(</span><span class="token3">[</span><span class="token6">1</span><span class="token3">,</span><span class="token6">2</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span><span class="token">//false php7.2以前致命错误demo6() must be an instance of iterable</span>
<span class="token">//具体类名或接口名</span>
<span class="token5">function</span> <span class="token4">demo9</span><span class="token3">(</span>Exception $param<span class="token3">)</span><span class="token3">{</span>
<span class="token4">print_r</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">//demo9(new Exception('哈哈'));</span>
<span class="token">//demo9(new A());//致命错误 demo3() must be an instance of Exception,</span>
```
```
## **3.返回值类型声明**
可用的类型与参数声明中可用的类型相同。即支持:具体类名接口名(php5.0),self(php5.0),array(php5.1),callable(php5.4),string(php7.0),int(php7.0),float(php7.0),bool(php7.0),iterable(php7.1),void(php7.1),object(php7.2)
> 注意指定类型后不能返回null,php7.1在类型前加?可解决此问题
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">demo</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">:</span>int<span class="token3">{</span>
<span class="token5">return</span> $param<span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo</span><span class="token3">(</span><span class="token5">null</span><span class="token3">)</span><span class="token3">;</span><span class="token">//7.0致命错误</span>
<span class="token5">function</span> <span class="token4">demo1</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">:</span><span class="token1">?</span>int<span class="token3">{</span>
<span class="token5">return</span> $param<span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo1</span><span class="token3">(</span><span class="token5">null</span><span class="token3">)</span><span class="token3">;</span><span class="token">//php7.1类型前加上?就能接受及返回null</span>
<span class="token5">function</span> <span class="token4">demo</span><span class="token3">(</span><span class="token1">?</span>int $param<span class="token3">)</span><span class="token3">:</span><span class="token1">?</span>int<span class="token3">{</span>
<span class="token5">return</span> $param<span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">demo</span><span class="token3">(</span><span class="token5">null</span><span class="token3">)</span><span class="token3">;</span><span class="token">//php7.1类型前加上?就能接受及返回null</span>
```
```
## **4.三元运算新增null合并运算符??**
当第一个表达式的值不存在或者为null时返回第二个表达式的值,否则返回第一个表达式的值,详情参看其他--三元运算章节
```
<pre class="calibre10">```
$username <span class="token1">=</span> $_GET<span class="token3">[</span><span class="token2">'user'</span><span class="token3">]</span> <span class="token1">?</span><span class="token1">?</span> <span class="token2">'nobody'</span><span class="token3">;</span>
echo $username<span class="token3">;</span><span class="token">//nobody</span>
```
```
## **5.太空船操作符<=>(组合比较符)**
太空船操作符用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1。 比较的原则是沿用 PHP 的常规比较规则进行的。
```
<pre class="calibre10">```
<span class="token">// 整数</span>
echo <span class="token6">1</span> <span class="token1"><=</span><span class="token1">></span> <span class="token6">1</span><span class="token3">;</span> <span class="token">// 0</span>
echo <span class="token6">1</span> <span class="token1"><=</span><span class="token1">></span> <span class="token6">2</span><span class="token3">;</span> <span class="token">// -1</span>
echo <span class="token6">2</span> <span class="token1"><=</span><span class="token1">></span> <span class="token6">1</span><span class="token3">;</span> <span class="token">// 1</span>
<span class="token">// 浮点数</span>
echo <span class="token6">1.5</span> <span class="token1"><=</span><span class="token1">></span> <span class="token6">1.5</span><span class="token3">;</span> <span class="token">// 0</span>
echo <span class="token6">1.5</span> <span class="token1"><=</span><span class="token1">></span> <span class="token6">2.5</span><span class="token3">;</span> <span class="token">// -1</span>
echo <span class="token6">2.5</span> <span class="token1"><=</span><span class="token1">></span> <span class="token6">1.5</span><span class="token3">;</span> <span class="token">// 1</span>
<span class="token">// 字符串</span>
echo <span class="token2">"a"</span> <span class="token1"><=</span><span class="token1">></span> <span class="token2">"a"</span><span class="token3">;</span> <span class="token">// 0</span>
echo <span class="token2">"a"</span> <span class="token1"><=</span><span class="token1">></span> <span class="token2">"b"</span><span class="token3">;</span> <span class="token">// -1</span>
echo <span class="token2">"b"</span> <span class="token1"><=</span><span class="token1">></span> <span class="token2">"a"</span><span class="token3">;</span> <span class="token">// 1</span>
```
```
## **6.define支持定义数组**
自从PHP5.6后,使用const数组也能被定义为常量,define在PHP7中被实现
## **7.支持[匿名类](https://www.php.net/manual/zh/language.oop5.anonymous.php)**
现在支持通过new class来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义
```
<pre class="calibre10">```
interface <span class="token4">Logger</span> <span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">log</span><span class="token3">(</span>string $msg<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
class <span class="token4">Application</span> <span class="token3">{</span>
private $logger<span class="token3">;</span>
public <span class="token5">function</span> <span class="token4">getLogger</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> Logger <span class="token3">{</span>
<span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>logger<span class="token3">;</span>
<span class="token3">}</span>
public <span class="token5">function</span> <span class="token4">setLogger</span><span class="token3">(</span>Logger $logger<span class="token3">)</span> <span class="token3">{</span>
$this<span class="token1">-</span><span class="token1">></span>logger <span class="token1">=</span> $logger<span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span>
$app <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Application</span><span class="token3">;</span>
$app<span class="token1">-</span><span class="token1">></span><span class="token4">setLogger</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">class</span> implements <span class="token4">Logger</span> <span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">log</span><span class="token3">(</span>string $msg<span class="token3">)</span> <span class="token3">{</span>
echo $msg<span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span>$app<span class="token1">-</span><span class="token1">></span><span class="token4">getLogger</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//object(class@anonymous)#2 (0) {}</span>
```
```
## [**8.Unicode字符编码表**](https://www.cnblogs.com/chris-oil/p/8677309.html)
中日韩统一表意文字(CJK Unified Ideographs),外加一些特殊的字符;用 \[ \\u2E80-\\uFE4F\]
```
<pre class="calibre10">```
echo <span class="token2">'\u{2E80}'</span><span class="token3">;</span><span class="token">//\u{2E80} 必须双引号</span>
echo <span class="token2">"\u{2E80}"</span><span class="token3">;</span><span class="token">//⺀</span>
```
```
## **9.增强之前的[assert()](https://www.php.net/manual/zh/function.assert.php)的方法**
简单但却最精确的定义一个*表达式*的方式就是“任何有值的东西”
早期assert是一个函数,php7是一个语法结构(在php语言中是用来判断一个表达式是否成立。返回true or false;)
老版本的API出于兼容目的将继续被维护,assert()现在是一个语言结构,
断言在PHP 5,这必须是一个字符串或者一个布尔计算测试。在PHP 7中,这也可以是**返回值的任何表达式**,该值将被执行,其结果用于指示断言是否成功或失败
**php7新增的的ini配置如下:**
**zend.assertions**
1:生成并执行代码(开发模式)
0:生成代码,但在运行时绕过它
-1:不生成代码(生产模式)
> **zend.assertions=1**
## **assert.exception**
//1:当断言失败时抛出,方法是抛出作为异常提供的对象,或者在没有提供异常时抛出一个新的AssertionError对象
//0:使用或生成一个Throwable,如前所述,但只生成一个基于该对象的警告,而不是抛出它(兼容PHP 5行为)
> **assert.exception=0**
```
<pre class="calibre10">```
<span class="token4">assert</span><span class="token3">(</span><span class="token6">true</span> <span class="token1">==</span> <span class="token6">false</span><span class="token3">)</span><span class="token3">;</span>
echo <span class="token2">'Hi!'</span><span class="token3">;</span>
zend<span class="token3">.</span>assertions<span class="token1">=</span><span class="token6">0</span>时输出:
Hi<span class="token1">!</span>
zend<span class="token3">.</span>assertions<span class="token1">=</span><span class="token6">1</span>并且assert<span class="token3">.</span>exception<span class="token1">=</span><span class="token6">0</span>时输出:
Warning<span class="token3">:</span> <span class="token4">assert</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> <span class="token4">assert</span><span class="token3">(</span><span class="token6">true</span> <span class="token1">==</span> <span class="token6">false</span><span class="token3">)</span> failed <span class="token5">in</span> <span class="token1">-</span> on line <span class="token6">2</span>
Hi<span class="token1">!</span>
zend<span class="token3">.</span>assertions<span class="token1">=</span><span class="token6">1</span>并且assert<span class="token3">.</span>exception<span class="token1">=</span><span class="token6">1</span>时输出:
Fatal error<span class="token3">:</span> Uncaught AssertionError<span class="token3">:</span> <span class="token4">assert</span><span class="token3">(</span><span class="token6">true</span> <span class="token1">==</span> <span class="token6">false</span><span class="token3">)</span> <span class="token5">in</span> <span class="token1">-</span><span class="token3">:</span><span class="token6">2</span>
Stack trace<span class="token3">:</span>
#<span class="token6">0</span> <span class="token1">-</span><span class="token3">(</span><span class="token6">2</span><span class="token3">)</span><span class="token3">:</span> <span class="token4">assert</span><span class="token3">(</span><span class="token6">false</span><span class="token3">,</span> <span class="token2">'assert(true == ...'</span><span class="token3">)</span>
#<span class="token6">1</span> <span class="token3">{</span>main<span class="token3">}</span>
thrown <span class="token5">in</span> <span class="token1">-</span> on line <span class="token6">2</span>
```
```
## **10.为unserialize()提供过滤**
```
<pre class="calibre10">```
<span class="token">//将所有对象分为__PHP_Incomplete_Class对象</span>
$data <span class="token1">=</span> <span class="token4">unserialize</span><span class="token3">(</span>$foo<span class="token3">,</span> <span class="token3">[</span><span class="token2">"allowed_classes"</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">false</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//将所有对象分为__PHP_Incomplete_Class 对象 除了ClassName1和ClassName2</span>
$data <span class="token1">=</span> <span class="token4">unserialize</span><span class="token3">(</span>$foo<span class="token3">,</span> <span class="token3">[</span><span class="token2">"allowed_classes"</span> <span class="token1">=</span><span class="token1">></span> <span class="token3">[</span><span class="token2">"ClassName1"</span><span class="token3">,</span> <span class="token2">"ClassName2"</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//默认行为,和 unserialize($foo)相同</span>
$data <span class="token1">=</span> <span class="token4">unserialize</span><span class="token3">(</span>$foo<span class="token3">,</span> <span class="token3">[</span><span class="token2">"allowed_classes"</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">true</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span>
```
```
## **11.增加Closure::call支持**
Closure::call将一个闭包函数动态绑定到一个新的对象实例并调用执行该函数,
```
<pre class="calibre10">```
class <span class="token4">Value</span> <span class="token3">{</span>
protected $value<span class="token3">;</span>
public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>$value<span class="token3">)</span> <span class="token3">{</span>
$this<span class="token1">-</span><span class="token1">></span>value <span class="token1">=</span> $value<span class="token3">;</span>
<span class="token3">}</span>
public <span class="token5">function</span> <span class="token4">getValue</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>value<span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span>
$three <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Value</span><span class="token3">(</span><span class="token6">3</span><span class="token3">)</span><span class="token3">;</span>
$four <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Value</span><span class="token3">(</span><span class="token6">4</span><span class="token3">)</span><span class="token3">;</span>
$closure <span class="token1">=</span> <span class="token5">function</span> <span class="token3">(</span>$delta<span class="token3">)</span> <span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span><span class="token4">getValue</span><span class="token3">(</span><span class="token3">)</span> <span class="token1">+</span> $delta<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span><span class="token3">;</span>
$closure<span class="token1">-</span><span class="token1">></span><span class="token4">call</span><span class="token3">(</span>$three<span class="token3">,</span> <span class="token6">4</span><span class="token3">)</span><span class="token3">;</span>
$closure<span class="token1">-</span><span class="token1">></span><span class="token4">call</span><span class="token3">(</span>$four<span class="token3">,</span> <span class="token6">4</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">// outputs int(7),int(8)</span>
```
```
```
<pre class="calibre10">```
class <span class="token4">Test</span>
<span class="token3">{</span>
public $name <span class="token1">=</span> <span class="token2">"lixuan"</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">//PHP7和PHP5.6都可以</span>
$getNameFunc <span class="token1">=</span> <span class="token5">function</span> <span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>name<span class="token3">;</span>
<span class="token3">}</span><span class="token3">;</span>
$name <span class="token1">=</span> $getNameFunc<span class="token1">-</span><span class="token1">></span><span class="token4">bindTo</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Test</span><span class="token3">,</span> <span class="token2">'Test'</span><span class="token3">)</span><span class="token3">;</span>
echo $<span class="token4">name</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//PHP7可以,PHP5.6报错</span>
$getX <span class="token1">=</span> <span class="token5">function</span> <span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> $this<span class="token1">-</span><span class="token1">></span>name<span class="token3">;</span>
<span class="token3">}</span><span class="token3">;</span>
echo $getX<span class="token1">-</span><span class="token1">></span><span class="token4">call</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">Test</span><span class="token3">)</span><span class="token3">;</span>
```
```
## **12.新增整数除法函数**
intdiv 接收两个参数作为被除数和除数,返回他们相除结果的整数部分。
```
<pre class="calibre10">```
<span class="token">// 7/2=3余1 值保留整数部分3</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">intdiv</span><span class="token3">(</span><span class="token6">7</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//int(3)</span>
```
```
## **13.新增加的 IntlChar 类**
旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。Intl是Pecl扩展,使用前需要编译进PHP中,也可apt-get/yum/port install php5-intl
```
<pre class="calibre10">```
<span class="token4">printf</span><span class="token3">(</span><span class="token2">'%x'</span><span class="token3">,</span> IntlChar<span class="token3">:</span><span class="token3">:</span>CODEPOINT_MAX<span class="token3">)</span><span class="token3">;</span>
echo IntlChar<span class="token3">:</span><span class="token3">:</span><span class="token4">charName</span><span class="token3">(</span><span class="token2">'@'</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span>IntlChar<span class="token3">:</span><span class="token3">:</span><span class="token4">ispunct</span><span class="token3">(</span><span class="token2">'!'</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
```
```
以上例程会输出:
10ffff
COMMERCIAL AT
bool(true)
CSPRNG
## **14.新增两个跨平台函数:** 可用于生成salt、密钥或初始化向量
兼容windows,linux或者其他大多数平台,如果不兼容抛出异常
**random\_bytes** — 生成加密安全的伪随机字节
```
<pre class="calibre10">```
<span class="token">//随机字节的长度设置为5</span>
$bytes <span class="token1">=</span> <span class="token4">random_bytes</span><span class="token3">(</span><span class="token6">5</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$bytes<span class="token3">)</span><span class="token3">;</span>
<span class="token">//转换为十六进制值</span>
$hexadecimal <span class="token1">=</span> <span class="token4">bin2hex</span><span class="token3">(</span>$bytes<span class="token3">)</span><span class="token3">;</span>
<span class="token4">var_dump</span><span class="token3">(</span>$hexadecimal<span class="token3">)</span><span class="token3">;</span><span class="token">//类似8c7c0481d6的字符串</span>
```
```
使用下面的函数来创建随机的令牌,并且还从令牌中创建了一个salt。我在我的应用程序中使用它来防止CSRF攻击
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">RandomToken</span><span class="token3">(</span>$length <span class="token1">=</span> <span class="token6">32</span><span class="token3">)</span><span class="token3">{</span>
<span class="token5">if</span><span class="token3">(</span><span class="token1">!</span><span class="token4">isset</span><span class="token3">(</span>$length<span class="token3">)</span> <span class="token1">||</span> <span class="token4">intval</span><span class="token3">(</span>$length<span class="token3">)</span> <span class="token1"><=</span> <span class="token6">8</span> <span class="token3">)</span><span class="token3">{</span>
$length <span class="token1">=</span> <span class="token6">32</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">function_exists</span><span class="token3">(</span><span class="token2">'random_bytes'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> <span class="token4">bin2hex</span><span class="token3">(</span><span class="token4">random_bytes</span><span class="token3">(</span>$length<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">function_exists</span><span class="token3">(</span><span class="token2">'mcrypt_create_iv'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> <span class="token4">bin2hex</span><span class="token3">(</span><span class="token4">mcrypt_create_iv</span><span class="token3">(</span>$length<span class="token3">,</span> MCRYPT_DEV_URANDOM<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">function_exists</span><span class="token3">(</span><span class="token2">'openssl_random_pseudo_bytes'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token5">return</span> <span class="token4">bin2hex</span><span class="token3">(</span><span class="token4">openssl_random_pseudo_bytes</span><span class="token3">(</span>$length<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span>
<span class="token5">function</span> <span class="token4">Salt</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span>
<span class="token5">return</span> <span class="token4">substr</span><span class="token3">(</span><span class="token4">strtr</span><span class="token3">(</span><span class="token4">base64_encode</span><span class="token3">(</span><span class="token4">hex2bin</span><span class="token3">(</span><span class="token4">RandomToken</span><span class="token3">(</span><span class="token6">32</span><span class="token3">)</span><span class="token3">)</span><span class="token3">)</span><span class="token3">,</span> <span class="token2">'+'</span><span class="token3">,</span> <span class="token2">'.'</span><span class="token3">)</span><span class="token3">,</span> <span class="token6">0</span><span class="token3">,</span> <span class="token6">44</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
echo <span class="token3">(</span><span class="token4">RandomToken</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
echo <span class="token2">'<br>'</span><span class="token3">;</span>
echo <span class="token4">Salt</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">/*
调试上面的几个函数
*/</span>
<span class="token5">function</span> <span class="token4">RandomTokenDebug</span><span class="token3">(</span>$length <span class="token1">=</span> <span class="token6">32</span><span class="token3">)</span><span class="token3">{</span>
<span class="token5">if</span><span class="token3">(</span><span class="token1">!</span><span class="token4">isset</span><span class="token3">(</span>$length<span class="token3">)</span> <span class="token1">||</span> <span class="token4">intval</span><span class="token3">(</span>$length<span class="token3">)</span> <span class="token1"><=</span> <span class="token6">8</span> <span class="token3">)</span><span class="token3">{</span>
$length <span class="token1">=</span> <span class="token6">32</span><span class="token3">;</span>
<span class="token3">}</span>
$randoms <span class="token1">=</span> <span class="token4">array</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">function_exists</span><span class="token3">(</span><span class="token2">'random_bytes'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
$randoms<span class="token3">[</span><span class="token2">'random_bytes'</span><span class="token3">]</span> <span class="token1">=</span> <span class="token4">bin2hex</span><span class="token3">(</span><span class="token4">random_bytes</span><span class="token3">(</span>$length<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">function_exists</span><span class="token3">(</span><span class="token2">'mcrypt_create_iv'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
$randoms<span class="token3">[</span><span class="token2">'mcrypt_create_iv'</span><span class="token3">]</span> <span class="token1">=</span> <span class="token4">bin2hex</span><span class="token3">(</span><span class="token4">mcrypt_create_iv</span><span class="token3">(</span>$length<span class="token3">,</span> MCRYPT_DEV_URANDOM<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">function_exists</span><span class="token3">(</span><span class="token2">'openssl_random_pseudo_bytes'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
$randoms<span class="token3">[</span><span class="token2">'openssl_random_pseudo_bytes'</span><span class="token3">]</span> <span class="token1">=</span> <span class="token4">bin2hex</span><span class="token3">(</span><span class="token4">openssl_random_pseudo_bytes</span><span class="token3">(</span>$length<span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">return</span> $randoms<span class="token3">;</span>
<span class="token3">}</span>
echo <span class="token2">'<br>'</span><span class="token3">;</span>
print_r <span class="token3">(</span><span class="token4">RandomTokenDebug</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
```
```
**random\_int**(int`$min`,int`$max`) :int —生成加密安全的伪随机整数
生成适合在非常重要的公正的结果情况下使用的加密随机整数,例如在扑克游戏中洗牌时
```
<pre class="calibre10">```
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">random_int</span><span class="token3">(</span><span class="token6">100</span><span class="token3">,</span> <span class="token6">999</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//int(248)</span>
<span class="token4">var_dump</span><span class="token3">(</span><span class="token4">random_int</span><span class="token3">(</span><span class="token1">-</span><span class="token6">1000</span><span class="token3">,</span> <span class="token6">0</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//int(-898)</span>
```
```
## **15.新增preg\_replace\_callback\_array()函数,比preg\_replace\_callback()函数简洁**
在 PHP 7 之前,当使用 preg\_replace\_callback() 函数的时候, 由于针对每个正则表达式都要执行回调函数,可能导致过多的分支代码。 而使用新加的 preg\_replace\_callback\_array() 函数, 可以使得代码更加简洁。 现在,可以使用一个关联数组来对每个正则表达式注册回调函数, 正则表达式本身作为关联数组的键, 而对应的回调函数就是关联数组的值。
## **16.session\_start()可以接受一个array作为参数**
现在,session\_start()函数可以接收一个数组作为参数,可以覆盖php.ini中session的配置项。
比如,把cache\_limiter设置为私有的,同时在阅读完session后立即关闭
```
<pre class="calibre10">```
<span class="token4">session_start</span><span class="token3">(</span><span class="token3">[</span><span class="token2">'cache_limiter'</span> <span class="token1">=</span><span class="token1">></span> <span class="token2">'private'</span><span class="token3">,</span>
<span class="token2">'read_and_close'</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">true</span><span class="token3">,</span>
<span class="token3">]</span><span class="token3">)</span><span class="token3">;</span>
```
```
## **17.生成器中引入其他生成器**
在生成器中可以引入另一个或几个生成器,只需要写yield from functionName1
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">generator1</span><span class="token3">(</span><span class="token3">)</span>
<span class="token3">{</span>
yield <span class="token6">1</span><span class="token3">;</span>
yield <span class="token6">2</span><span class="token3">;</span>
yield from <span class="token4">generator2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
yield from <span class="token4">generator3</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">function</span> <span class="token4">generator2</span><span class="token3">(</span><span class="token3">)</span>
<span class="token3">{</span>
yield <span class="token6">3</span><span class="token3">;</span>
yield <span class="token6">4</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token5">function</span> <span class="token4">generator3</span><span class="token3">(</span><span class="token3">)</span>
<span class="token3">{</span>
yield <span class="token6">5</span><span class="token3">;</span>
yield <span class="token6">6</span><span class="token3">;</span>
<span class="token3">}</span>
foreach <span class="token3">(</span><span class="token4">generator1</span><span class="token3">(</span><span class="token3">)</span> as $val<span class="token3">)</span> <span class="token3">{</span>
echo $val<span class="token3">,</span> <span class="token2">" "</span><span class="token3">;</span>
<span class="token3">}</span>
```
```
## **18.生成器可以返回表达式**
生成器(读取超大文件很有用,节约内存)
它允许在生成器函数中通过使用 return 语法来返回一个表达式 (但是不允许返回引用值), 可以通过调用 Generator::getReturn() 方法来获取生成器的返回值, 但是这个方法只能在生成器完成产生工作以后调用一次
```
<pre class="calibre10">```
$gen <span class="token1">=</span> <span class="token3">(</span><span class="token5">function</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>
yield <span class="token6">1</span><span class="token3">;</span>
yield <span class="token6">2</span><span class="token3">;</span>
<span class="token5">return</span> <span class="token6">3</span><span class="token3">;</span>
<span class="token3">}</span><span class="token3">)</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
foreach <span class="token3">(</span>$gen as $val<span class="token3">)</span> <span class="token3">{</span>
echo $val<span class="token3">,</span> PHP_EOL<span class="token3">;</span><span class="token">// 1 2</span>
<span class="token3">}</span>
<span class="token">//首先执行函数 该函数遇到yield停止并将该yied的值发送给foreach</span>
echo $gen<span class="token1">-</span><span class="token1">></span><span class="token4">getReturn</span><span class="token3">(</span><span class="token3">)</span><span class="token3">,</span> PHP_EOL<span class="token3">;</span><span class="token">//3</span>
结果:
<span class="token6">1</span> <span class="token6">2</span> <span class="token6">3</span>
```
```
php全局保留字可以声明使用
```
<pre class="calibre10">```
class <span class="token4">View</span> <span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">include</span><span class="token3">(</span>View $view<span class="token3">)</span> <span class="token3">{</span>
<span class="token">//...</span>
<span class="token">//include关键字可以当普通字符串关键字一样被使[其他](%E5%85%B6%E4%BB%96.md)用</span>
<span class="token3">}</span>
<span class="token3">}</span>
```
```
允许在克隆表达式上访问对象成员,例如:*(clone $foo)->bar()*。
# **php7.1新特性**
## **参数和返回类型支持null,前提是在类型前加?**
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">test1</span><span class="token3">(</span><span class="token1">?</span>string $name<span class="token3">)</span>
<span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$name<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token">//在默认非严格模式下,标量string、int、float和 bool 之间会强制转化,与php7相比php7.1可接受null</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token2">'dash'</span><span class="token3">)</span><span class="token3">;</span><span class="token">//'dash'</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token5">null</span><span class="token3">)</span><span class="token3">;</span><span class="token">//NULL</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token6">30</span><span class="token3">)</span><span class="token3">;</span><span class="token">//'30'</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token6">30.1</span><span class="token3">)</span><span class="token3">;</span><span class="token">//'30.1'</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token6">true</span><span class="token3">)</span><span class="token3">;</span><span class="token">//'1'</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token3">[</span><span class="token6">1</span><span class="token3">,</span><span class="token6">2</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">stdClass</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
<span class="token5">function</span> <span class="token4">test1</span><span class="token3">(</span>$name<span class="token3">)</span><span class="token3">:</span><span class="token1">?</span>string
<span class="token3">{</span>
<span class="token5">return</span> $name<span class="token3">;</span>
<span class="token3">}</span>
echo <span class="token4">gettype</span><span class="token3">(</span><span class="token4">test1</span><span class="token3">(</span><span class="token2">'dash'</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//string</span>
echo <span class="token4">gettype</span><span class="token3">(</span><span class="token4">test1</span><span class="token3">(</span><span class="token5">null</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//NULL</span>
echo <span class="token4">gettype</span><span class="token3">(</span><span class="token4">test1</span><span class="token3">(</span><span class="token6">30</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//string</span>
echo <span class="token4">gettype</span><span class="token3">(</span><span class="token4">test1</span><span class="token3">(</span><span class="token6">30.1</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//string</span>
echo <span class="token4">gettype</span><span class="token3">(</span><span class="token4">test1</span><span class="token3">(</span><span class="token6">true</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span><span class="token">//string</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token3">[</span><span class="token6">1</span><span class="token3">,</span><span class="token6">2</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">stdClass</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
```
```
## **php7.1返回类型新增void**
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">test</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> void
<span class="token3">{</span>
<span class="token5">return</span> <span class="token2">'hello'</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">test</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
<span class="token5">function</span> <span class="token4">test1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> void
<span class="token3">{</span>
<span class="token5">return</span> <span class="token5">null</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">test1</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
<span class="token5">function</span> <span class="token4">test2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> void
<span class="token3">{</span>
<span class="token5">return</span> <span class="token2">''</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">test2</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//致命错误</span>
<span class="token5">function</span> <span class="token4">test3</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> void
<span class="token3">{</span>
<span class="token5">return</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">test3</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//正常</span>
<span class="token5">function</span> <span class="token4">test4</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> void
<span class="token3">{</span>
<span class="token">//无返回值</span>
<span class="token3">}</span>
<span class="token4">test4</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//正常</span>
```
```
## **短数组语法(*\[\]*)现在作为list()语法的一个备选项,可以用于将数组的值赋给一些变量(包括在*foreach*中)**
```
<pre class="calibre10">```
$data <span class="token1">=</span> <span class="token3">[</span>
<span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token2">'Tom'</span><span class="token3">]</span><span class="token3">,</span>
<span class="token3">[</span><span class="token6">2</span><span class="token3">,</span> <span class="token2">'Fred'</span><span class="token3">]</span><span class="token3">,</span>
<span class="token3">]</span><span class="token3">;</span>
<span class="token">//php之前支持格式</span>
<span class="token4">list</span><span class="token3">(</span>$id1<span class="token3">,</span> $name1<span class="token3">)</span> <span class="token1">=</span> $data<span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">;</span>
foreach <span class="token3">(</span>$data as <span class="token4">list</span><span class="token3">(</span>$id<span class="token3">,</span> $name<span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token">// logic here with $id and $name</span>
<span class="token3">}</span>
<span class="token">//php7新增的短数组[]格式</span>
<span class="token3">[</span>$id1<span class="token3">,</span> $name1<span class="token3">]</span> <span class="token1">=</span> $data<span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">;</span>
foreach <span class="token3">(</span>$data as <span class="token3">[</span>$id<span class="token3">,</span> $name<span class="token3">]</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token">// logic here with $id and $name</span>
<span class="token3">}</span>
```
```
PHP 5 里,list() 从最右边的参数开始赋值; PHP 7 里,list() 从最左边的参数开始赋值
```
<pre class="calibre10">```
$info <span class="token1">=</span> <span class="token4">array</span><span class="token3">(</span><span class="token2">'coffee'</span><span class="token3">,</span> <span class="token2">'brown'</span><span class="token3">,</span> <span class="token2">'caffeine'</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">list</span><span class="token3">(</span>$a<span class="token3">[</span><span class="token6">0</span><span class="token3">]</span><span class="token3">,</span> $a<span class="token3">[</span><span class="token6">1</span><span class="token3">]</span><span class="token3">,</span> $a<span class="token3">[</span><span class="token6">2</span><span class="token3">]</span><span class="token3">)</span> <span class="token1">=</span> $info<span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$a<span class="token3">)</span><span class="token3">;</span>
php5输出<span class="token3">:</span><span class="token3">[</span><span class="token6">2</span><span class="token1">=</span><span class="token1">></span><span class="token2">'caffeine'</span><span class="token3">,</span><span class="token6">1</span><span class="token1">=</span><span class="token1">></span><span class="token2">'brown'</span><span class="token3">,</span><span class="token6">0</span><span class="token1">=</span><span class="token1">></span><span class="token2">'coffee'</span><span class="token3">]</span>
php7输出<span class="token3">:</span><span class="token3">[</span><span class="token6">0</span><span class="token1">=</span><span class="token1">></span><span class="token2">'coffee'</span><span class="token3">,</span><span class="token6">1</span><span class="token1">=</span><span class="token1">></span><span class="token2">'brown'</span><span class="token3">,</span><span class="token6">2</span><span class="token1">=</span><span class="token1">></span><span class="token2">'caffeine'</span><span class="token3">]</span>
```
```
在 PHP 7.1.0 之前的版本,list() 仅能用于数字索引的数组,并假定数字索引从 0 开始
从 PHP 7.1.0 开始,list() 可以包含显式的键,可赋值到任意表达式。 可以混合使用数字和字符串键。但是不能混合有键和无键不能混用
```
<pre class="calibre10">```
$data <span class="token1">=</span> <span class="token3">[</span>
<span class="token3">[</span><span class="token2">"id"</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">1</span><span class="token3">,</span> <span class="token2">"name"</span> <span class="token1">=</span><span class="token1">></span> <span class="token2">'Tom'</span><span class="token3">]</span><span class="token3">,</span>
<span class="token3">[</span><span class="token2">"id"</span> <span class="token1">=</span><span class="token1">></span> <span class="token6">2</span><span class="token3">,</span> <span class="token2">"name"</span> <span class="token1">=</span><span class="token1">></span> <span class="token2">'Fred'</span><span class="token3">]</span><span class="token3">,</span>
<span class="token3">]</span><span class="token3">;</span>
foreach <span class="token3">(</span>$data as <span class="token3">[</span><span class="token2">"id"</span> <span class="token1">=</span><span class="token1">></span> $id<span class="token3">,</span> <span class="token2">"name"</span> <span class="token1">=</span><span class="token1">></span> $name<span class="token3">]</span><span class="token3">)</span> <span class="token3">{</span>
echo <span class="token2">"id: $id, name: $name\n"</span><span class="token3">;</span><span class="token">//id: 1, name: Tom id: 2, name: Fred</span>
<span class="token3">}</span>
echo PHP_EOL<span class="token3">;</span>
<span class="token4">list</span><span class="token3">(</span><span class="token6">1</span> <span class="token1">=</span><span class="token1">></span> $second<span class="token3">,</span> <span class="token6">3</span> <span class="token1">=</span><span class="token1">></span> $fourth<span class="token3">)</span> <span class="token1">=</span> <span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">]</span><span class="token3">;</span>
echo $second<span class="token3">.</span>$fourth<span class="token3">.</span>PHP_EOL<span class="token3">;</span><span class="token">//2 4</span>
```
```
## **字符串偏移量可以为负,表示为一个从字符串结尾开始的偏移量**
```
<pre class="calibre10">```
<span class="token4">var_dump</span><span class="token3">(</span><span class="token2">"abcdef"</span><span class="token3">[</span><span class="token1">-</span><span class="token6">2</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span><span class="token">//e</span>
<span class="token">//b在abcdef首次出现的位置 从结尾倒数第5个偏移开始查找</span>
echo <span class="token4">strpos</span><span class="token3">(</span><span class="token2">'abcdef'</span><span class="token3">,</span><span class="token2">'b'</span><span class="token3">,</span> <span class="token1">-</span><span class="token6">5</span><span class="token3">)</span><span class="token3">;</span><span class="token">//1</span>
a b c d e f
<span class="token6">0</span> <span class="token6">1</span> <span class="token6">2</span> <span class="token6">3</span> <span class="token6">4</span> <span class="token6">5</span>
<span class="token1">-</span><span class="token6">6</span> <span class="token1">-</span><span class="token6">5</span> <span class="token1">-</span><span class="token6">4</span> <span class="token1">-</span><span class="token6">3</span> <span class="token1">-</span><span class="token6">2</span> <span class="token1">-</span><span class="token6">1</span>
```
```
## **字符串负偏移在简单的变量解析语法中也支持能了**
```
<pre class="calibre10">```
$string <span class="token1">=</span> <span class="token2">'bar'</span><span class="token3">;</span>
echo <span class="token2">"The last character of '$string' is '$string[-1]'.\n"</span><span class="token3">;</span><span class="token">//The last character of 'bar' is 'r'.</span>
```
```
## **对服务器推送的支持现在已经被加入到 CURL 扩展(v7.46)中**
```
<pre class="calibre10">```
$transfers <span class="token1">=</span> <span class="token6">1</span><span class="token3">;</span>
$callback <span class="token1">=</span> <span class="token5">function</span><span class="token3">(</span>$parent_ch<span class="token3">,</span> $pushed_ch<span class="token3">,</span> array $headers<span class="token3">)</span> use <span class="token3">(</span><span class="token1">&</span>$transfers<span class="token3">)</span> <span class="token3">{</span>
$transfers<span class="token1">++</span><span class="token3">;</span> <span class="token">// 增量,以跟踪并发请求的数量</span>
<span class="token5">return</span> CURL_PUSH_OK<span class="token3">;</span>
<span class="token3">}</span><span class="token3">;</span>
$mh <span class="token1">=</span> <span class="token4">curl_multi_init</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_multi_setopt</span><span class="token3">(</span>$mh<span class="token3">,</span> CURLMOPT_PIPELINING<span class="token3">,</span> CURLPIPE_MULTIPLEX<span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_multi_setopt</span><span class="token3">(</span>$mh<span class="token3">,</span> CURLMOPT_PUSHFUNCTION<span class="token3">,</span> $callback<span class="token3">)</span><span class="token3">;</span>
$ch <span class="token1">=</span> <span class="token4">curl_init</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_URL<span class="token3">,</span> <span class="token2">"https://localhost:8080/index.html"</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_HTTP_VERSION<span class="token3">,</span> <span class="token6">3</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_RETURNTRANSFER<span class="token3">,</span> <span class="token6">1</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">// 调式/局部填充</span>
<span class="token">//curl_setopt($ch, CURLOPT_VERBOSE, 1); // 是否会输出curl调试信息</span>
<span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_SSL_VERIFYHOST<span class="token3">,</span> <span class="token6">0</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// self-signed cert</span>
<span class="token4">curl_setopt</span><span class="token3">(</span>$ch<span class="token3">,</span> CURLOPT_SSL_VERIFYPEER<span class="token3">,</span> <span class="token6">0</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// self-signed cert</span>
<span class="token4">curl_multi_add_handle</span><span class="token3">(</span>$mh<span class="token3">,</span> $ch<span class="token3">)</span><span class="token3">;</span>
$active <span class="token1">=</span> <span class="token5">null</span><span class="token3">;</span>
<span class="token5">do</span> <span class="token3">{</span>
$status <span class="token1">=</span> <span class="token4">curl_multi_exec</span><span class="token3">(</span>$mh<span class="token3">,</span> $active<span class="token3">)</span><span class="token3">;</span>
<span class="token5">do</span> <span class="token3">{</span>
$info <span class="token1">=</span> <span class="token4">curl_multi_info_read</span><span class="token3">(</span>$mh<span class="token3">)</span><span class="token3">;</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token6">false</span> <span class="token1">!==</span> $info <span class="token1">&&</span> $info<span class="token3">[</span><span class="token2">'msg'</span><span class="token3">]</span> <span class="token1">==</span> CURLMSG_DONE<span class="token3">)</span> <span class="token3">{</span>
$handle <span class="token1">=</span> $info<span class="token3">[</span><span class="token2">'handle'</span><span class="token3">]</span><span class="token3">;</span>
<span class="token5">if</span> <span class="token3">(</span>$handle <span class="token1">!==</span> <span class="token5">null</span><span class="token3">)</span> <span class="token3">{</span>
$transfers<span class="token1">--</span><span class="token3">;</span> <span class="token">// 减量 剩余请求</span>
$out <span class="token1">=</span> <span class="token4">curl_multi_getcontent</span><span class="token3">(</span>$info<span class="token3">[</span><span class="token2">'handle'</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 响应体</span>
<span class="token4">curl_multi_remove_handle</span><span class="token3">(</span>$mh<span class="token3">,</span> $handle<span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_close</span><span class="token3">(</span>$handle<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span>
<span class="token3">}</span> <span class="token5">while</span> <span class="token3">(</span>$info<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span> <span class="token5">while</span> <span class="token3">(</span>$transfers<span class="token3">)</span><span class="token3">;</span>
<span class="token4">curl_multi_close</span><span class="token3">(</span>$mh<span class="token3">)</span><span class="token3">;</span>
```
```
## **异步信号处理**
一个新的名为 pcntl\_async\_signals() 的方法现在被引入, 用于启用无需 ticks (这会带来很多额外的开销)的异步信号处理。
```
<pre class="calibre10">```
<span class="token4">pcntl_async_signals</span><span class="token3">(</span><span class="token6">true</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 打开异步信号</span>
<span class="token4">pcntl_signal</span><span class="token3">(</span>SIGHUP<span class="token3">,</span> <span class="token5">function</span><span class="token3">(</span>$sig<span class="token3">)</span> <span class="token3">{</span>
echo <span class="token2">"SIGHUP\n"</span><span class="token3">;</span>
<span class="token3">}</span><span class="token3">)</span><span class="token3">;</span>
<span class="token4">posix_kill</span><span class="token3">(</span><span class="token4">posix_getpid</span><span class="token3">(</span><span class="token3">)</span><span class="token3">,</span> SIGHUP<span class="token3">)</span><span class="token3">;</span>
以上例程会输出:
SIGHUP
```
```
## **新增Closure::fromCallable() 将callables转为闭包**
Closure新增了一个静态方法,用于将callable快速地 转为一个Closure 对象。
```
<pre class="calibre10">```
class <span class="token4">Test</span>
<span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">exposeFunction</span><span class="token3">(</span><span class="token3">)</span>
<span class="token3">{</span>
<span class="token5">return</span> Closure<span class="token3">:</span><span class="token3">:</span><span class="token4">fromCallable</span><span class="token3">(</span><span class="token3">[</span>$this<span class="token3">,</span> <span class="token2">'privateFunction'</span><span class="token3">]</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
private <span class="token5">function</span> <span class="token4">privateFunction</span><span class="token3">(</span>$param<span class="token3">)</span>
<span class="token3">{</span>
<span class="token4">var_dump</span><span class="token3">(</span>$param<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span>
<span class="token">//((new Test)->exposeFunction())('some value');</span>
$privFunc <span class="token1">=</span> <span class="token3">(</span><span class="token5">new</span> <span class="token4">Test</span><span class="token3">)</span><span class="token1">-</span><span class="token1">></span><span class="token4">exposeFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
$<span class="token4">privFunc</span><span class="token3">(</span><span class="token2">'some value'</span><span class="token3">)</span><span class="token3">;</span><span class="token">//some value</span>
```
```
# **php7.2新特性**
## **新的对象类型**
这种新的对象类型, object, 引进了可用于逆变(contravariant)参数输入和协变(covariant)返回任何对象类型
```
<pre class="calibre10">```
<span class="token5">function</span> <span class="token4">test</span><span class="token3">(</span>object $obj<span class="token3">)</span> <span class="token3">:</span> object
<span class="token3">{</span>
<span class="token5">return</span> <span class="token5">new</span> <span class="token4">SplQueue</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token4">test</span><span class="token3">(</span><span class="token5">new</span> <span class="token4">StdClass</span><span class="token3">(</span><span class="token3">)</span><span class="token3">)</span><span class="token3">;</span>
```
```
## **既可以通过 php.ini 也可以运行时通过 dl(string $library): bool载入一个 PHP 扩展**
在 安全模式(php5.4废除),总是无法使用 dl()
不推荐,存在安全风险
如果加载模块的功能是无效或者禁用的(既可以通过设置关闭 enable\_dl(仅对 Apache 模块版本的 PHP 有效) 设置
```
<pre class="calibre10">```
<span class="token">// 加载一个扩展的例子,基于操作系统</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token1">!</span><span class="token4">extension_loaded</span><span class="token3">(</span><span class="token2">'sqlite'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span><span class="token">//检查一个扩展是否已经加载</span>
<span class="token5">if</span> <span class="token3">(</span><span class="token4">strtoupper</span><span class="token3">(</span><span class="token4">substr</span><span class="token3">(</span>PHP_OS<span class="token3">,</span> <span class="token6">0</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">)</span><span class="token3">)</span> <span class="token1">===</span> <span class="token2">'WIN'</span><span class="token3">)</span> <span class="token3">{</span>
<span class="token4">dl</span><span class="token3">(</span><span class="token2">'php_sqlite.dll'</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span> <span class="token5">else</span> <span class="token3">{</span>
<span class="token4">dl</span><span class="token3">(</span><span class="token2">'sqlite.so'</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
<span class="token3">}</span>
<span class="token">// 或者,使用常量 PHP_SHLIB_SUFFIX </span>
<span class="token5">if</span> <span class="token3">(</span><span class="token1">!</span><span class="token4">extension_loaded</span><span class="token3">(</span><span class="token2">'sqlite'</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
$prefix <span class="token1">=</span> <span class="token3">(</span>PHP_SHLIB_SUFFIX <span class="token1">===</span> <span class="token2">'dll'</span><span class="token3">)</span> <span class="token1">?</span> <span class="token2">'php_'</span> <span class="token3">:</span> <span class="token2">''</span><span class="token3">;</span>
<span class="token4">dl</span><span class="token3">(</span>$prefix <span class="token3">.</span> <span class="token2">'sqlite.'</span> <span class="token3">.</span> PHP_SHLIB_SUFFIX<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
```
```
## **允许重写抽象方法**
当一个抽象类继承于另外一个抽象类的时候,继承后的抽象类可以重写被继承的抽象类的抽象方法
```
<pre class="calibre10">```
abstract class <span class="token4">A</span>
<span class="token3">{</span>
abstract <span class="token5">function</span> <span class="token4">test</span><span class="token3">(</span>string $s<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
abstract class <span class="token4">B</span> extends <span class="token4">A</span>
<span class="token3">{</span>
<span class="token">// 覆盖 - still maintaining contravariance for parameters and covariance for return</span>
abstract <span class="token5">function</span> <span class="token4">test</span><span class="token3">(</span>$s<span class="token3">)</span> <span class="token3">:</span> int<span class="token3">;</span>
<span class="token3">}</span>
```
```
## **重写方法和接口实现的参数类型现在可以省略**
```
<pre class="calibre10">```
interface <span class="token4">A</span>
<span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">Test</span><span class="token3">(</span>array $input<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
class <span class="token4">B</span> implements <span class="token4">A</span>
<span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">Test</span><span class="token3">(</span>$input<span class="token3">)</span><span class="token3">{</span><span class="token3">}</span> <span class="token">// 省略了$input的类型</span>
<span class="token3">}</span>
```
```
# **php7.3新特性**
## **更灵活的`Heredoc`和`Nowdoc`语法**
```
<pre class="calibre10">```
<span class="token">//heredoc可以解析变量,nowdoc则不能解析变量</span>
$name<span class="token1">=</span><span class="token2">'dash'</span><span class="token3">;</span>
<span class="token">//原heredoc</span>
$str<span class="token1">=</span><span class="token1"><</span><span class="token1"><</span><span class="token1"><</span>STR
这是文本第一行
这是文本第二行<span class="token3">.</span><span class="token3">{</span>$name<span class="token3">}</span>over<span class="token1">!</span>
STR<span class="token3">;</span>
echo $str<span class="token3">;</span><span class="token">//这是文本第一行 这是文本第二行.dashover!</span>
<span class="token">//原nowdoc</span>
$str <span class="token1">=</span> <span class="token1"><</span><span class="token1"><</span><span class="token1"><</span><span class="token2">'EOD'</span>
Example of string
spanning multiple lines
using nowdoc syntax<span class="token3">.</span><span class="token3">{</span>$name<span class="token3">}</span>over!
EOD<span class="token3">;</span>
echo $str<span class="token3">;</span><span class="token">//Example of string spanning multiple lines using nowdoc syntax.{$name}over!</span>
<span class="token">//可以使用缩进,使用缩进时doc内容的每行都会跳过相应的缩进</span>
(下例两行的缩进都被剥除了)
$str<span class="token1">=</span><span class="token1"><</span><span class="token1"><</span><span class="token1"><</span>STR
这是文本第一行 <span class="token1">|</span>
这是文本第二行 STR<span class="token3">;</span> <span class="token1">|</span>
STR<span class="token3">;</span>
echo $str<span class="token3">;</span><span class="token">// 这是文本第一行 | 这是文本第二行 STR; |</span>
两行的缩进都被剥除了
<span class="token">//结束标记不再需要独立一行</span>
$str<span class="token1">=</span><span class="token1"><</span><span class="token1"><</span><span class="token1"><</span>STR
这是文本第一行
这是文本第二行
STR<span class="token3">;</span>echo $str<span class="token3">;</span><span class="token">//这是文本第一行 这是文本第二行</span>
<span class="token">//在某些情况下不用紧跟分号了</span>
$data <span class="token1">=</span> <span class="token3">[</span><span class="token2">"元素"</span><span class="token3">,</span> <span class="token1"><</span><span class="token1"><</span><span class="token1"><</span>STR
这是文本第一行
这是文本第二行
STR<span class="token3">,</span> <span class="token6">42</span><span class="token3">,</span><span class="token3">]</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$data<span class="token3">)</span><span class="token3">;</span><span class="token">//Array ( [0] => 元素 [1] => 这是文本第一行 这是文本第二行 [2] => 42 )</span>
$str<span class="token1">=</span><span class="token1"><</span><span class="token1"><</span><span class="token1"><</span>STR
这是文本第一行
这是文本第二行
STR
echo $str<span class="token3">;</span><span class="token">//这中情况就会报错</span>
```
```
## **数组析构与list结构支持引用赋值**
$v = \[10, 20\];
\[$a, &$b\] = $v;//短语法等同list($a, &$b)=$v;
$b += 10;
var\_dump($v, $a, $b);//array(2) { \[0\]=> int(10) \[1\]=> &int(30) } int(10) int(30)
## \*\* instanceof 运算符支持字面量语法\*\*
instanceof 的第一个运算数支持字面量,非对象型字面量检测的结果为 false
var\_dump("literal" instanceof stdClass);//false
var\_dump(42 instanceof stdClass);//false
var\_dump(new stdClass() instanceof stdClass);//true
## **支持调用时参数的末尾跟随逗号,但是定义是不行的**
function methodName($p1, $p2)
{
var\_dump($p1, $p2);
}
methodName(10, 20, );//10 20
## **BC 数学函数**
bcscale() 函数支持获取当前任意BC(精度的数学扩展)函数所使用的 scale。
bcscale(3);//设置所有bc数学函数的默认小数点保留位数
var\_dump(bcscale());//3
## **废弃大小写不敏感的常量**
将 TRUE 作为第三个参数传递给 define() 会导致一个废弃警告
## **命名捕获支持**
mb\_ereg\_ \*系列函数现在支持命名捕获。类似于mb\_ereg()的匹配函数现在将使用其组号和名称返回命名捕获,类似于PCRE:
```
<pre class="calibre10">```
<span class="token4">mb_ereg</span><span class="token3">(</span><span class="token2">'(?<word>\w+)'</span><span class="token3">,</span> <span class="token2">'国'</span><span class="token3">,</span> $matches<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span><span class="token">//Array ( [0] => [0 => "国", 1 => "国", "word" => "国"];</span>
<span class="token4">mb_ereg</span><span class="token3">(</span><span class="token2">'(?<word>\w+)'</span><span class="token3">,</span> <span class="token2">'国<=>家'</span><span class="token3">,</span> $matches<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span><span class="token">//Array ( [0] => [0 => "国", 1 => "国", "word" => "国"];</span>
<span class="token4">mb_ereg</span><span class="token3">(</span><span class="token2">'(?<word>\w+)'</span><span class="token3">,</span> <span class="token2">'国家'</span><span class="token3">,</span> $matches<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span><span class="token">//Array ( [0] => 国家 [1] => 国家 [word] => 国家 )</span>
```
```
此外,mb\_ereg\_replace()现在支持 \\k<>和\\k''表示法来引用替换字符串中的命名捕获:
```
<pre class="calibre10">```
<span class="token">//mb_ereg_replace ($pattern , $replacement , $string中匹配) //在string中匹配pattern,匹配成功则替换成replacement</span>
$str<span class="token1">=</span><span class="token4">mb_ereg_replace</span><span class="token3">(</span><span class="token2">'\s*(?<word>\w+)\s*'</span><span class="token3">,</span> <span class="token2">"_\k<word>_\k'word'_"</span><span class="token3">,</span> <span class="token2">' foo '</span><span class="token3">)</span><span class="token3">;</span>
echo $str<span class="token3">;</span><span class="token">// => "_foo_foo_"</span>
```
```
# **php7.4新特性**
## **预加载**
`PHP`预加载可以极大的提高性能
- 优点:在`PHP 7.4`以前,如果你使用了框架来开发,每次请求文件就必须加载和重新编译。预加载在框架启动时在内存中加载文件,而且在后续请求中永久有效。
- 缺点:性能的提升会在其他方面花费很大的代价,每次预加载的文件发生改变时,框架需要重新启动。
## **类属性现在支持类型声明**
除了`void`和`callable`外,所有的类型都支持
因此,我们可以放心使用`bool`,`int`,`float`,`string`,`array`,`object`,`iterable`,`self`,`parent`
```
<pre class="calibre10">```
class <span class="token4">User</span> <span class="token3">{</span>
public int $id<span class="token3">;</span>
public string $name<span class="token3">;</span>
public <span class="token1">?</span>Foo $foo<span class="token3">;</span>
<span class="token3">}</span>
```
```
## **短闭包函数**
```
<pre class="calibre10">```
array_map <span class="token3">(</span><span class="token5">function</span><span class="token3">(</span>$arr1_value<span class="token3">,</span> $arr2_value<span class="token3">,</span> $arrN_value<span class="token3">)</span><span class="token3">{</span>
<span class="token">//return $arr1_value.$arr2_value.$arrN_value;</span>
<span class="token3">}</span><span class="token3">,</span>
$arr1<span class="token3">,</span>
$arr2<span class="token3">,</span>
$arrN
<span class="token3">)</span><span class="token3">;</span>
<span class="token">//原有特性</span>
<span class="token5">function</span> <span class="token4">cube</span><span class="token3">(</span>$n<span class="token3">)</span><span class="token3">{</span>
<span class="token5">return</span> <span class="token3">(</span>$n <span class="token1">*</span> $n <span class="token1">*</span> $n<span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
$a <span class="token1">=</span> <span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">,</span> <span class="token6">5</span><span class="token3">]</span><span class="token3">;</span>
$b <span class="token1">=</span> <span class="token4">array_map</span><span class="token3">(</span><span class="token2">'cube'</span><span class="token3">,</span> $a<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$b<span class="token3">)</span><span class="token3">;</span>
<span class="token">//新特性</span>
$a <span class="token1">=</span> <span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">,</span> <span class="token6">5</span><span class="token3">]</span><span class="token3">;</span>
$res <span class="token1">=</span> <span class="token4">array_map</span><span class="token3">(</span><span class="token4">fn</span><span class="token3">(</span>$n<span class="token3">)</span> <span class="token1">=</span><span class="token1">></span> $n <span class="token1">*</span> $n <span class="token1">*</span> $n<span class="token3">,</span> $a<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$res<span class="token3">)</span><span class="token3">;</span>
$a <span class="token1">=</span> <span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">]</span><span class="token3">;</span>
$b <span class="token1">=</span> <span class="token3">[</span><span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">,</span> <span class="token6">5</span><span class="token3">]</span><span class="token3">;</span>
$res <span class="token1">=</span> <span class="token4">array_map</span><span class="token3">(</span><span class="token4">fn</span><span class="token3">(</span>$av<span class="token3">,</span>$bv<span class="token3">)</span> <span class="token1">=</span><span class="token1">></span> $av<span class="token1">*</span>$bv<span class="token3">,</span> $a<span class="token3">,</span>$b<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$res<span class="token3">)</span><span class="token3">;</span>
$a <span class="token1">=</span> <span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">]</span><span class="token3">;</span>
$b <span class="token1">=</span> <span class="token3">[</span><span class="token6">3</span><span class="token3">,</span> <span class="token6">4</span><span class="token3">,</span> <span class="token6">5</span><span class="token3">]</span><span class="token3">;</span>
$res <span class="token1">=</span> <span class="token4">array_map</span><span class="token3">(</span><span class="token4">fn</span><span class="token3">(</span><span class="token1">?</span>int $av<span class="token3">,</span><span class="token1">?</span>int $bv<span class="token3">)</span><span class="token3">:</span> int <span class="token1">=</span><span class="token1">></span> $av<span class="token1">*</span>$bv<span class="token3">,</span> $a<span class="token3">,</span>$b<span class="token3">)</span><span class="token3">;</span>
<span class="token4">print_r</span><span class="token3">(</span>$res<span class="token3">)</span><span class="token3">;</span>
<span class="token">//如果你想通过引用返回一个值,应该使用以下语法</span>
fn<span class="token1">&</span><span class="token3">(</span>$x<span class="token3">)</span> <span class="token1">=</span><span class="token1">></span> $x
<span class="token">//总结:</span>
<span class="token">//它们以fn关键字开始</span>
<span class="token">//它们只能有一个表达式,即return语句</span>
<span class="token">//不允许return关键字</span>
<span class="token">//参数和返回类型可以是限定类型</span>
```
```
## **Null 合并运算符**
```
<pre class="calibre10">```
$data<span class="token3">[</span><span class="token2">'date'</span><span class="token3">]</span> <span class="token1">?</span><span class="token1">?</span><span class="token1">=</span> <span class="token5">new</span> <span class="token4">DateTime</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token">//相当于之前的</span>
$data<span class="token3">[</span><span class="token2">'date'</span><span class="token3">]</span> <span class="token1">=</span> $data<span class="token3">[</span><span class="token2">'date'</span><span class="token3">]</span> <span class="token1">?</span><span class="token1">?</span> <span class="token5">new</span> <span class="token4">DateTime</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
或:
<span class="token5">if</span> <span class="token3">(</span><span class="token1">!</span><span class="token4">isset</span><span class="token3">(</span>$data<span class="token3">[</span><span class="token2">'date'</span><span class="token3">]</span><span class="token3">)</span><span class="token3">)</span> <span class="token3">{</span>
$data<span class="token3">[</span><span class="token2">'date'</span><span class="token3">]</span> <span class="token1">=</span> <span class="token5">new</span> <span class="token4">DateTime</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span>
<span class="token3">}</span>
```
```
## **数组扩展运算符**
现在你可以在数组中使用展开运算符:
**注意**:只对数字索引有效
```
<pre class="calibre10">```
$arrayA <span class="token1">=</span> <span class="token3">[</span><span class="token6">1</span><span class="token3">,</span> <span class="token6">2</span><span class="token3">,</span> <span class="token6">3</span><span class="token3">]</span><span class="token3">;</span>
$arrayB <span class="token1">=</span> <span class="token3">[</span><span class="token6">4</span><span class="token3">,</span> <span class="token6">5</span><span class="token3">]</span><span class="token3">;</span>
$result <span class="token1">=</span> <span class="token3">[</span><span class="token6">0</span><span class="token3">,</span> <span class="token3">.</span><span class="token3">.</span><span class="token3">.</span>$arrayA<span class="token3">,</span> <span class="token3">.</span><span class="token3">.</span><span class="token3">.</span>$arrayB<span class="token3">,</span> <span class="token6">6</span> <span class="token3">,</span><span class="token6">7</span><span class="token3">]</span><span class="token3">;</span>
<span class="token">// [0, 1, 2, 3, 4, 5, 6, 7]</span>
```
```
## **自定义对象序列化**
添加了两个新的魔术方法:`__serialize` 和`__unserialize`
## **数字分隔符**
允许使用下划线更直观的分隔数值
```
<pre class="calibre10">```
$unformattedNumber <span class="token1">=</span> <span class="token6">107925284.88</span><span class="token3">;</span>
<span class="token">//新特性</span>
$formattedNumber <span class="token1">=</span> <span class="token6">107</span>_925_284<span class="token3">.</span><span class="token6">88</span><span class="token3">;</span>
```
```
## **支持反射引用**
`PHP 7.4`将会新增`ReflectionReference`类
## **改进的类型差异(协变返回和逆变参数)**
[协变和逆变](https://link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E5%258D%258F%25E5%258F%2598%25E4%25B8%258E%25E9%2580%2586%25E5%258F%2598)
[百度百科的解释](https://link.zhihu.com/?target=https%3A//baike.baidu.com/item/%25E5%258D%258F%25E5%258F%2598)
协变与逆变(Covariance and contravariance )是在计算机科学中,描述具有父/子型别关系的多个型别通过型别构造器、构造出的多个复杂型别之间是否有父/子型别关系的用语。
- Invariant (不变): 包好了所有需求类型
- Covariant (协变):类型从通用到具体
- Contravariant (逆变): 类型从具体到通用目前,PHP 主要具有`Invariant`的参数类型,并且大多数是`Invariant`的返回类型,这就意味着当我是 T 参数类型或者返回类型时,子类也必须是 T 的参数类型或者返回类型。但是往往会需要处理一些特殊情况,比如具体的返回类型,或者通用的输入类型。而[RFC](https://link.zhihu.com/?target=https%3A//wiki.php.net/rfc/covariant-returns-and-contravariant-parameters)的这个提案就提议,PHP7.4 添加协变返回和逆变参数,以下是提案给出来的例子:协变返回:
```
<pre class="calibre17">```
class <span class="token4">Parent</span> <span class="token3">{</span><span class="token3">}</span>
class <span class="token4">Child</span> extends <span class="token4">Parent</span> <span class="token3">{</span><span class="token3">}</span>
class <span class="token4">A</span>
<span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">covariantReturnTypes</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> Parent
<span class="token3">{</span> <span class="token">/* … */</span> <span class="token3">}</span>
<span class="token3">}</span>
class <span class="token4">B</span> extends <span class="token4">A</span>
<span class="token3">{</span>
public <span class="token5">function</span> <span class="token4">covariantReturnTypes</span><span class="token3">(</span><span class="token3">)</span><span class="token3">:</span> Child
<span class="token3">{</span> <span class="token">/* … */</span> <span class="token3">}</span>
<span class="token3">}</span>
```
```
- php更新内容
- 其他
- empty、isset、is_null
- echo 输出bool值
- if真假情况
- 常量
- define与const(php5.3) 类常量
- 递归
- 单元测试
- 面向对象
- 全局变量域超全局变量
- php网络相关
- 支持的协议和封装协议(如http,php://input)
- 上下文(Context)选项和参数
- 过滤器
- http请求及模拟登录
- socket
- streams
- swoole
- 超全局变量
- $_ENV :存储了一些系统的环境变量
- $_COOKIE
- $_SESSION
- $_FILES
- $_SERVER
- 正则
- php正则函数
- 去除文本中的html、xml的标签
- 特殊符号
- \r\n
- 模式修正符
- 分组
- 断言
- 条件表达式
- 递归表达式 (?R)
- 固化分组
- 正则例子
- 框架
- 自动加载spl_autoload_register
- 时间函数
- 文件操作
- 文件的上传下载
- 常见的mimi类型
- 文件断点续传
- 下载文件防盗链
- 破解防盗链
- 无限分类
- 短信验证码
- 短信宝
- 视频分段加载
- phpDoc注释
- 流程控制代替语法
- 三元运算
- @错误抑制符
- 字符编码
- PHP CLI模式开发
- 配置可修改范围
- CGI、FastCGI和PHP-FPM关系图解
- No input file specified的解决方法
- SAPI(PHP常见的四种运行模式)
- assert断言
- 类基础
- 类的三大特性:封装,继承,多态
- 魔术方法
- 辅助查询(*)
- extends继承
- abstract 抽象类
- interface 接口(需要implements实现)
- 抽象类和接口的区别
- 多态
- static
- final
- serialize与unserialize
- instanceof 判断后代子类
- 类型约束
- clone克隆
- ::的用法
- new self()与new static()
- this、self、static、parent、super
- self、static、parent:后期静态绑定
- PHP的静态变量
- php导入
- trait
- 动态调用类方法
- 参数及类型申明
- 方法的重载覆盖
- return $a && $b
- 设计思想
- 依赖注入与依赖倒置
- 创建型模式(创建类对象)
- (*)单例模式
- (*)工厂模式
- 原型模式(在方法里克隆this)
- 创建者模式
- 结构型模式
- 适配器模式(Adapter)
- 桥接模式
- 装饰模式
- 组合模式
- 外观模式(门面(Facade)模式)
- 享元模式
- 代理模式
- 行为型模式
- (*)观察者模式
- (*)迭代器模式(Iterator)
- 模板方法模式 Template
- 命令模式(Command)
- 中介者模式(Mediator)
- 状态模式(State)
- 职责链模式 (Chainof Responsibility)
- 策略模式(Strategy)
- 已知模式-备忘录模式(Memento)
- 深度模式-解释器模式(Interpreter)
- 深度模式-访问者模式(Visitor)
- (*)注册树(注射器、注册表)模式
- 函数参考
- 影响 PHP 行为的扩展
- APC扩展(过时)
- APCu扩展
- APD扩展(过时)
- bcompiler扩展(过时)
- BLENC扩展 (代码加密 实验型)
- Componere扩展(7.1+)
- 错误处理扩展(PHP 核心)
- FFI扩展
- htscanner扩展
- inclued扩展
- Memtrack扩展
- OPcache扩展(5.5.0内部集成)
- Output Control扩展(核心)
- PHP Options/Info扩展(核心)
- phpdbg扩展(5.6+内部集成)
- runkit扩展
- runkit7扩展
- scream扩展
- uopz扩展
- Weakref扩展
- WinCache扩展
- Xhprof扩展
- 音频格式操作
- ID3
- KTaglib
- oggvorbis
- OpenAL
- 身份认证服务
- KADM5
- Radius
- 针对命令行的扩展
- Ncurses(暂无人维护)
- Newt(暂无人维护)
- Readline
- 压缩与归档扩展
- Bzip2
- LZF
- Phar
- Rar
- Zip
- Zlib
- 信用卡处理
- 加密扩展
- Crack(停止维护)
- CSPRNG(核心)
- Hash扩展(4.2内置默认开启、7.4核心)
- Mcrypt(7.2移除)
- Mhash(过时)
- OpenSSL(*)
- 密码散列算法(核心)
- Sodium(+)
- 数据库扩展
- 数据库抽象层
- 针对各数据库系统对应的扩展
- 日期与时间相关扩展
- Calendar
- 日期/时间(核心)
- HRTime(*)
- 文件系统相关扩展
- Direct IO
- 目录(核心)
- Fileinfo(内置)
- 文件系统(核心)
- Inotify
- Mimetype(过时)
- Phdfs
- Proctitle
- xattr
- xdiff
- 国际化与字符编码支持
- Enchant
- FriBiDi
- Gender
- Gettext
- iconv(内置默认开启)
- intl
- 多字节字符串(mbstring)
- Pspell
- Recode(将要过时)
- 图像生成和处理
- Cairo
- Exif
- GD(内置)
- Gmagick
- ImageMagick
- 邮件相关扩展
- Cyrus
- IMAP
- Mail(核心)
- Mailparse
- vpopmail(实验性 )
- 数学扩展
- BC Math
- GMP
- Lapack
- Math(核心)
- Statistics
- Trader
- 非文本内容的 MIME 输出
- FDF
- GnuPG
- haru(实验性)
- Ming(实验性)
- wkhtmltox(*)
- PS
- RPM Reader(停止维护)
- RpmInfo
- XLSWriter Excel操作(*)
- 进程控制扩展
- Eio
- Ev
- Expect
- Libevent
- PCNTL
- POSIX
- 程序执行扩展(核心)
- parallel
- pthreads(*)
- pht
- Semaphore
- Shared Memory
- Sync
- 其它基本扩展
- FANN
- GeoIP(*)
- JSON(内置)
- Judy
- Lua
- LuaSandbox
- Misc(核心)
- Parsekit
- SeasLog(-)
- SPL(核心)
- SPL Types(实验性)
- Streams(核心)
- Swoole(*)
- Tidy扩展
- Tokenizer
- URLs(核心)
- V8js(*)
- Yaml
- Yaf
- Yaconf(核心)
- Taint(检测xss字符串等)
- Data Structures
- 其它服务
- 网络(核心)
- cURL(*)
- Event(*)
- chdb
- FAM
- FTP
- Gearman
- Gopher
- Gupnp
- Hyperwave API(过时)
- LDAP(+)
- Memcache
- Memcached(+)
- mqseries
- RRD
- SAM
- ScoutAPM
- SNMP
- Sockets
- SSH2
- Stomp
- SVM
- SVN(试验性的)
- TCP扩展
- Varnish
- YAZ
- YP/NIS
- 0MQ(ZeroMQ、ZMQ)消息系统
- ZooKeeper
- 搜索引擎扩展
- mnoGoSearch
- Solr
- Sphinx
- Swish(实验性)
- 针对服务器的扩展
- Apache
- FastCGI 进程管理器
- IIS
- NSAPI
- Session 扩展
- Msession
- Sessions
- Session PgSQL
- 文本处理
- BBCode
- CommonMark(markdown解析)
- Parle
- PCRE( 核心)
- POSIX Regex
- ssdeep
- 字符串(核心)
- 变量与类型相关扩展
- 数组(核心)
- 类/对象(核心)
- Classkit(未维护)
- Ctype
- Filter扩展
- 函数处理(核心)
- quickhash扩展
- 反射扩展(核心)
- Variable handling(核心)
- Web 服务
- OAuth
- SCA(实验性)
- SOAP
- Yar
- XML-RPC(实验性)
- Windows 专用扩展
- COM
- win32ps
- win32service
- XML 操作
- DOM(内置,默认开启)
- libxml(内置 默认开启)
- SDO(停止维护)
- SDO-DAS-Relational(试验性的)
- SDO DAS XML
- SimpleXML(内置,5.12+默认开启)
- WDDX
- XMLDiff
- XML 解析器(Expat 解析器 默认开启)
- XMLReader(5.1+内置默认开启)
- XMLWriter(5.1+内置默认开启)
- XSL(内置)
- 图形用户界面(GUI) 扩展
- UI
- 预定义类
- PHP SPL(PHP 标准库)
- 数据结构
- SplDoublyLinkedList(双向链表)
- SplStack(栈 先进后出)
- SplQueue(队列)
- SplHeap(堆)
- SplMaxHeap(最大堆)
- SplMinHeap(最小堆)
- SplPriorityQueue(堆之优先队列)
- SplFixedArray(阵列【数组】)
- SplObjectStorage(映射【对象存储】)
- 迭代器
- DirectoryIterator类
- 文件处理
- SplFileInfo
- SplFileObject
- SplTempFileObject
- 接口 interface
- Countable
- OuterIterator
- RecursiveIterator
- SeekableIterator
- 异常
- 各种类及接口
- SplSubject
- SplObserver
- ArrayObject(将数组作为对象操作)
- SPL 函数
- 预定义接口
- Traversable(遍历)接口
- Iterator(迭代器)接口
- IteratorAggregate(聚合式迭代器)接口
- ArrayAccess(数组式访问)接口
- Serializable 序列化接口
- JsonSerializable
- Closure 匿名函数(闭包)类
- Generator生成器类
- 生成器(php5.5+)
- 反射
- 一、反射(reflection)类
- 二、Reflector 接口
- ReflectionClass 类报告了一个类的有关信息。
- ReflectionFunctionAbstract
- ReflectionParameter 获取函数或方法参数的相关信息
- ReflectionProperty 类报告了类的属性的相关信息。
- ReflectionClassConstant类报告有关类常量的信息。
- ReflectionZendExtension 类返回Zend扩展相关信息
- ReflectionExtension 报告了一个扩展(extension)的有关信息。
- 三、ReflectionGenerator类用于获取生成器的信息
- 四、ReflectionType 类用于获取函数、类方法的参数或者返回值的类型。
- 五、反射的应用场景
- git
- Git代码同时上传到GitHub和Gitee(码云)
- Git - 多人协同开发利器,团队协作流程规范与注意事项
- 删除远程仓库的文件
- 创建composer项目
- composer安装及设置
- composer自动加载讲解
- phpsdudy的composer操作
- swoole笔记
- 安装及常用Cli操作
- TCP
- 4种回调函数的写法
- phpRedis
- API
- API详细
- redis DB 概念:
- 通用命令:rawCommand
- Connection
- Server
- List
- Set
- Zset
- Hash
- string
- Keys
- 事物
- 发布订阅
- 流streams
- Geocoding 地理位置
- lua脚本
- Introspection 自我检测
- biMap
- 原生
- php-redis 操作类 封装
- redis 队列解决秒杀解决超卖:
- Linux
- Centos8(Liunx) 中安装PHP7.4 的三种方法和删除它的三种方法
- 权限设计
- ACL
- RBAC
- RBAC0
- RBAC1
- RBAC2
- RBAC3
- 例子
- ABAC 基于属性的访问控制
- 总结:SAAS后台权限设计案例分析
- casbin-权限管理框架
- 开始使用
- casbinAPI
- Think-Casbin
- 单点登录(SSO)
- OAuth授权
- OAuth 2.0 的四种方式
- 更新令牌
- 例子:第三方登录
- 微服务架构下的统一身份认证和授权
- 杂项
- SSL证书
- sublime Emmet的快捷语法
- 免费翻译接口
- 免费空间
- xss过滤
- HTML Purifier文档
- xss例子
- 实用小函数
- PHP操作Excel
- 架构师必须知道的26项PHP安全实践
- 模版布局
- smarty模版
- blade
- twig
- 大佬博客
- 优化
- 缓存
- opcache
- memcache
- 数据库
- 主从分布
- 数据库设计
- 笔记
- 配置
- nginx 主从配置
- nginx 负载均衡的配置
- 手动搭建Redis集群和MySQL主从同步(非Docker)
- Redis Cluster集群
- mysql主从同步
- 用安卓手机搭建 web 服务器
- 软件选择
- 扩展库列表
- 代码审计
- 漏洞挖掘的思路
- 命令注入
- 代码注入
- XSS 反射型漏洞
- XSS 存储型漏洞
- 本地包含与远程包含
- sql注入
- 函数
- 注释
- 步骤
- information_schema
- sql注入的分类
- 实战
- 防御
- CSRF 跨站请求伪造
- 计动态函数执行与匿名函数执行
- unserialize反序列化漏洞
- 覆盖变量漏洞
- 文件管理漏洞
- 文件上传漏洞
- 跳过登录
- URL编码对照表
- 浏览器插件开发
- 插件推荐
- 扩展文件manifest.json
- 不可视的background(常驻)页面
- 可视页面browser actions与page actions及八种展示方式
- 使用chrome.xxx API
- Google Chrome扩展与Web页面/服务器之间的交互
- Google Chrome扩展中的页面之间的数据通信
- inject-script
- chromeAPI
- pageAction
- alarms
- chrome.tabs
- chrome.runtime
- chrome.webRequest
- chrome.window
- chrome.storage
- chrome.contextMenus
- chrome.devtools
- chrome.extension
- 分类
- homepage_url 开发者或者插件主页
- 5种类型的JS对比及消息通信
- 其它补充
- 前端、移动端
- html5
- meta标签
- flex布局
- javascript
- 获取js对象所有方法
- dom加载
- ES6函数写法
- ES6中如何导入和导出模块
- 数组的 交集 差集 补集 并集
- bootstrap
- class速查
- 常见data属性
- 开源项目
- 会员 数据库表设计
- 程序执行
- 开发总结
- API接口
- API接口设计
- json转化
- app接口
