PHP新特性(php5.3-php5.6)

概述

从PHP5.3开始到PHP5.6版本,PHP每次版本更新不但做到了最大限度的向后兼容,同时还添加了许多新特性;
为我们开发现代WEB项目提供了极大的方便。我们可以在PHP官方文档的附录查阅相关更详细
内容。如果你想动手运行及演练各版本的示例代码,可以使用这个网站, 它可以向你展示PHP各版本下的运行结果。

命名空间

在php5.3中,终于引入了命名空间。通俗的理解,命名空间就是一种文件级封装、定义文件级作用域的方式。具体的作用就是解决用户自己编写的代码与项目内部同事之间、PHP内部、引入的第三方的类、函数、常量的命名冲突问题。 具体使用请见手册。

后期静态绑定

在PHP5.3中引入了后期静态绑定特性,用于在类的继承逻辑中引用静态调用的方法或属性;在此逻辑中静态调用方法或属性时,使用的不再是当前类,而是调用的类。请看下面例子,将静态调用和普通调用作了对比(方法的调用请看官方手册,本例展示的是属性)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Base {
public static $merchantId = 0;

public static function getMerchantId(){
// 普通引用和static静态引用对比
return [self::$merchantId, static::$merchantId];
}
}

class Google extends Base {
public static $merchantId = 100;
}

class Baidu extends Base {
public static $merchantId = 200;
}

$ret = Google::getMerchantId(); // [0, 100]
$ret = Baidu::getMerchantId(); // [0, 200]

goto关键字支持

goto 关键字可以用来将代码执行点跳转到程序中的另一位置。

匿名函数

匿名函数(Anonymous functions),也叫闭包函数(closures),允许临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。

1
2
3
4
$arr = array_map(function($v) {
return 'item_' . $v;
}, [2,4,6]);
// $arr输出为 ['item_2', 'item_4', 'item_6']

当然在匿名函数内部是无法直接使用外部作用域里的变量的,如果要使用,就必须通过use关键字。

1
2
3
4
5
$total = 0;
$arr = array_map(function($v) use(&$total) {
return $total += $v * 10;
}, [2,4,6]);
// $arr输出为 [20, 60, 120]

新增了两个魔术方法(__callStatic 、 __invoke)

在静态上下文中调用一个不可访问方法时,callStatic() 会被调用。
当尝试以调用函数的方式调用一个对象时,
invoke() 方法会被自动调用。

多行字符串表示法的变化

heredoc结构类似于多行且保持格式的双引号字符串, 而PHP5.3新增的 nowdoc结构是类似于多行且保持格式的单引号字符串。
nowdoc结构也用和heredoc结构一样的标记 <<<,但是跟在后面的标识符要用单引号括起来,即 <<<’EOT’。
在PHP5.3中heredoc结构也支持使用双引号,如 <<<”EOT”。这样就和heredoc结构在语法一达到了统一。

跑到了类外面的类常量

在PHP5.3.0以后,可以使用 const 关键字在类定义之外定义常量

1
2
const CONSTANT = 'Hello World';
echo CONSTANT; // Hello World

和用define定义常量不同的是,使用const关键字定义常量必须处于最顶端的作用区域,因为用此方法是在编译时定义的。
这就意味着不能在函数/循环体内/if语句之内用const来定义常量。

三目运算符

在PHP5.3.0之前,如果想直接判断表达式1的结果为true时就返回结果时,得在表达式2中重写一遍表达式1,现在可以省掉这一步了.

1
2
3
$str = '   hello ';
echo trim($str) ? trim($str) : 'default'; // hello
echo trim($str) ? : 'default'; // hello PHP >= 5.3.0

PHP5.4.0中的Trait

trait是PHP实现代码复用的又一机制,可很好的解决PHP的单一继承的局限性问题,又可减少添加了多继承的复杂度.可灵活组合trait进行组件式开发

  • 在类中引入trait后,其优先级关系为 基类方法 < trait引入的方法 < 本类中定义的方法, 优先级高的覆盖优先级低的
  • 可同时引入多个trait, 如果有方法名冲突,可使用insteadof操作符来明确指定使用冲突方法中的哪一个
  • trait也可引入其它的trait来组合使用
  • trait可定义抽象方法/静态方法
  • trait还可以定义属性,这时类中就不可再定义同名的属性

数组定义有了新花样

之前数组定义都是使用 array(), 到了5.4提供了新的定义语法:使用[]操作符

1
2
$a = [1, 2, 3, 4]; //相单于 $a = array(1, 2, 3, 4);
$a = ['one' => 1, 'two' => 2, 'three' => 3, 'four' => 4];

对于函数中返回数组的成员直接访问

之前对于函数中返回的数组,要先赋值给变量,然后再通过下标方式来方式,至少要2步;现在可以一步到位了.

1
2
3
4
function a(){
return [50, 100];
}
echo a()[1]; //100

实例化一个类时,也不需要必须赋值给一个变量再使用,可以直接调用

1
(new ExampleModel)->print();

同时对于方法的调用也支持表达式计算语法,如上面关于”后期静态绑定”的例子,可以改成这样:

1
2
3
$name = 'getMerchantId'; // 也可以是一个表达式计算结果
$ret = Google::{$name}();
$ret = Baidu::{$name}();

二进制直接量支持

PHP5.4中新增二进制直接量,例如:0b001001101

引入生成器

我觉得在PHP5.5中,最值得期待的新特性就是生成器。PHP通过yield关键字添加了对生成器的支持。 生成器提供了一种简单的方法来实现简单的迭代器,而省去实现Iterator接口的开销或复杂性。

新增 finally 关键字

PHP在5.5版本中加入了finally关键字, 这样可以做到不管try语句里有没有抛出异常或错误,在finally里的语句总是会执行.

foreach支持list()函数

1
2
3
4
5
6
7
8
9
$arr = [
[15, 'liming'],
[16, 'huahua'],
];
foreach ($arr as list($id, $name)) {
echo 'id:' . $id .','. 'name:' . $name . PHP_EOL;
}
//id:15,name:liming
//id:16,name:huahua

empty()函数升级

现在empty()函数支持任意表达式作为参数调用,而之前仅仅支持传入一个变量

数组和字符串支持直接下标引用

数组和字符串都直接访问下标引用,无需先赋值到一个变量再引用

1
2
echo [50,100,1000][2]; // 1000
echo 'PHP'[1]; // H

新的密码哈希API

这套密码哈希API是专门用于加密密码和校验密码的解决方案. 从5.5之后, 就不应该再使用md5(password) 方式来加密密码,这里提供了更好的方案.

新的密码哈希API

类常量/属性/函数参数默认值上的变化

在PHP 5.6之前的版本中,必须使用静态值(数值/字符串字面量)来定义类常量、声明属性和指定函数参数默认值, 在新版本中,一切变得更加灵活起来了;现在除了使用这些静态值外,还可以使用表达式(数学运算表达式/字符串连接表达式/类常量引用/数组)来定义.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const ONE = 1;
const TWO = ONE * 2;
const ARR = ['a', 'b'];

class C {
const THREE = TWO + 1;
const ONE_THIRD = ONE / self::THREE;
const SENTENCE = 'The value of THREE is ' . self::THREE;
const SEX = ['male', 'female'];

public $len = self::THREE ** 2; //幂运算

public function func1($a = ONE + self::THREE) {
return $a;
}

public function func2($sex = self::SEX) {
return $sex;
}
}

$c = new C;
echo $c->func1(). PHP_EOL; // 4
print\_r($c->func2()). PHP_EOL; //Array([0] => male [1] => female)
echo C::SENTENCE . PHP_EOL; // The value of THREE is 3
echo C::SEX[1] . PHP_EOL; //female
echo $c->len . PHP_EOL; // 9

使用 … 运算符定义可变长参数的函数

在函数定义处的形参列表里使用 …运算符后接变量名的方式可以让此形参变量接收到除了前面已经被其它形参变量接收到的所有的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function f($req, $opt = null, ...$params) {
// $params 是一个包含了剩余参数的数组
printf('$req: %d; $opt: %d; number of params: %d'."\n",
$req, $opt, count($params));
}

f(1);
f(1, 2);
f(1, 2, 3);
f(1, 2, 3, 4);
f(1, 2, 3, 4, 5);

//上例输出:
$req: 1; $opt: 0; number of params: 0
$req: 1; $opt: 2; number of params: 0
$req: 1; $opt: 2; number of params: 1
$req: 1; $opt: 2; number of params: 2
$req: 1; $opt: 2; number of params: 3

使用 … 运算符进行参数展开

在调用函数的时候,使用 … 运算符, 将数组和可遍历对象展开为函数参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function add($a, $b, $c) {
return $a + $b + $c;
}
$operators = [2, 3];
echo add(1, ...$operators) . PHP_EOL; // 6

//系统函数也可以
$arr = ['helloworld', 3, 3];
echo substr(...$arr); // low

//在PhpRedis扩展里,sAdd()方法使用这种方式调用就更方便
$redis->sAdd('key1' , 'member2', 'member3'); //普通调用

$memberArr = ['member2', 'member3'];// 参数展开调用
$redis->sAdd('key1', ...$memberArr);

幂运算表达式

加入右连接运算符 ** 来进行幂运算。同时也支持简写的 **= 运算符。

1
2
$a = 2;
$a **= 3; // 8

命名空间特性中use运算符功能增强

在之前的版本中只支持导入外部的类,在PHP5.6中use支持导入外部的函数和常量。对应的结构为 use function 和 use const。

1
2
3
4
5
use const Name\Space\CONSTANT;
use function Name\Space\func;

echo CONSTANT;
func();

加入__debugInfo()魔术方法

当使用var_dump()输出对象的时候,可以通过编写__debugInfo()函数来控制要输出的属性和值。

  • © 2015-2020 watson

请我喝杯咖啡吧~

支付宝
微信