Maison  >  Article  >  développement back-end  >  Explication détaillée des nouvelles fonctionnalités de PHP7.0 (exemples)

Explication détaillée des nouvelles fonctionnalités de PHP7.0 (exemples)

藏色散人
藏色散人avant
2019-03-20 13:56:424834parcourir


Explication détaillée des nouvelles fonctionnalités de PHP7.0 (exemples)

Cet article vise principalement à analyser en détail les nouvelles fonctionnalités de php7.0.

1. Performances et couche sous-jacente

PHP7 est deux fois plus rapide que PHP5.6

Le changement le plus important de php7 Il s'agit d'une énorme amélioration des performances et est proche du moteur d'exécution PHP HHVM développé par Facebook. Dans le test de performance de WordPress, la vitesse est 2 à 3 fois plus rapide que la version 5.6, ce qui réduit considérablement l'utilisation de la mémoire. PHP7 a également quelques changements dans le langage, comme l'ajout de déclarations de type de retour et l'ajout de nouveaux mots-clés réservés. En termes de sécurité, le mode sans échec PHP est supprimé, des guillemets magiques sont ajoutés, etc. De plus, la nouvelle version prend également en charge le 64 bits et contient la dernière version du moteur Zend.

Testez-le

Un exemple très simple, générez un tableau de 600 000 éléments et déterminez si la clé existe en recherchant la clé.

<?php
$a = [];
for($i=0;$i<600000;$i++){
  $a[$i] = $i;
}
foreach($a as $item) {
 array_key_exists($item, $a);
}

Nous avons testé les performances sur php5.6.11 et php7.0.4 respectivement.

php5.6.11

➜ time php 1.php
  0.67s user 0.06s system 67% cpu 1.078 total
➜ time php 1.php
  0.68s user 0.06s system 98% cpu 0.748 total
➜ time php 1.php
  0.65s user 0.06s system 67% cpu 1.052 total

En moyenne les trois fois, cela représente environ 0,65 seconde pour l'utilisateur, 0,06 seconde pour le système et un taux de CPU de 67 %. Environ 1 seconde au total.

En regardant la situation de php7

➜  time /usr/local/opt/php70/bin/php 1.php
  0.52s user 0.02s system 98% cpu 0.544 total
➜  time /usr/local/opt/php70/bin/php 1.php
  0.49s user 0.02s system 99% cpu 0.513 total
➜  time /usr/local/opt/php70/bin/php 1.php
  0.51s user 0.02s system 98% cpu 0.534 total

En comparaison, le temps d'utilisation de l'utilisateur a chuté d'environ 20 %, le temps d'utilisation du système a chuté de 70 % et le taux d'utilisation du processeur était aussi atteint 98 %. Le temps global est réduit à. 0,5 seconde.

En regardant cet exemple, l'efficacité est doublée. Pas mal en effet.

Regardez un autre exemple. Il génère également un tableau de 600 000 éléments pour déterminer si une valeur existe.

<?php
$a = [];
for($i=0;$i<600000;$i++){
    $a[$i] = $i;
}
foreach($a as $i) {
    array_search($i, $a);
}
?>

Regardez d'abord php5.6.11

➜  testPHP time php 2.php
0.68s user 0.03s system 66% cpu 1.077 total
➜  testPHP time php 2.php
0.68s user 0.02s system 98% cpu 0.710 total
➜  testPHP time php 2.php
0.68s user 0.02s system 98% cpu 0.713 total
➜  testPHP time php 2.php
0.69s user 0.02s system 98% cpu 0.721 total

Puis regardez php7.0.4

➜  testPHP time /usr/local/opt/php70/bin/php 2.php
0.12s user 0.02s system 69% cpu 0.201 total
➜  testPHP time /usr/local/opt/php70/bin/php 2.php
0.11s user 0.01s system 97% cpu 0.131 total
➜  testPHP time /usr/local/opt/php70/bin/php 2.php
0.11s user 0.01s system 96% cpu 0.130 total

Il est évident qu'il est plus de 6 fois plus rapide . pointu.

2. Nouvelles fonctionnalités

1. Plus de déclarations de types scalaires

Il existe désormais deux modes pour les scalaires en PHP : Application (par défaut) et mode strict. Les paramètres de type suivants sont désormais disponibles (en mode forcé ou strict) : string, int, float et bool. Ils étendent d'autres types introduits dans PHP5 : noms de classes, interfaces, tableaux et types de rappel. Dans l'ancienne version, les déclarations de paramètres de fonction ne pouvaient être que (Array $arr), (CLassName $obj), etc. Les types de base tels que Int, String, etc. ne pouvaient pas être déclarés.

Comment le comprenez-vous ? Dans les versions antérieures à php7, si l'on veut limiter le type de paramètres d'une fonction, il n'y en a que deux types : tableau ou classe.

Avant php7 :

class MyInfo
{
    public $a = 123;
    public function getInfo(array $a, $b)
    {
        var_dump($a, $b);
    }
}
function getClass(MyInfo $a) {
    var_dump($a->a);
}

Nous souhaitons limiter le premier paramètre de getInfo à un tableau, afin de pouvoir ajouter un tableau avant le paramètre $a. déclarer.

De même, nous voulons que le paramètre de getClass soit une classe, nous utilisons donc le className de cette classe pour la déclarer pour une utilisation obligatoire.

Avant php7, seuls ces deux scalaires pouvaient être utilisés.

Utilisons-le :

$info = new MyInfo();
$info->getInfo([1,2,3,4], 4);

Nous suivons la réglementation, passons le tableau comme premier paramètre, et bien sûr le résultat sera imprimé normalement :

➜  testPHP php 3.php
array(3) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
}
int(4)

Si Si nous n'installons pas les exigences, une erreur bien connue sera signalée :

$info = new MyInfo();
$info->getInfo(122, 0);

Rapport d'erreur :

PHP Catchable fatal error:  Argument 1 passed to MyInfo::getInfo() must be of the type array, integer given, called in /Users/yangyi/www/testPHP/3.php on line 25 and defined in /Users/yangyi/www/testPHP/3.php on line 8
PHP Stack trace:
PHP   1. {main}() /Users/yangyi/www/testPHP/3.php:0
PHP   2. MyInfo->getInfo() /Users/yangyi/www/testPHP/3.php:25

La même chose s'applique à l'utilisation de la classe :

$info = new MyInfo();
getClass($info);

Résultat de sortie :

➜  testPHP php 3.php
int(123)

De même, si on passe d'autres paramètres, une erreur sera signalée :

getClass(123);
➜  testPHP php 3.php
PHP Catchable fatal error:  Argument 1 passed to getClass() must be an instance of MyInfo, integer given, called in /Users/yangyi/www/testPHP/3.php on line 27 and defined in /Users/yangyi/www/testPHP/3.php on line 17
PHP Stack trace:
PHP   1. {main}() /Users/yangyi/www/testPHP/3.php:0
PHP   2. getClass() /Users/yangyi/www/testPHP/3.php:27

Revenons à ce php7 mise à niveau, qui a étendu le type scalaire et ajouté bool, int, string, float.

php7 a 2 modes : le mode obligatoire (par défaut) et le mode strict.

Mode forcé

Le mode forcé est le mode par défaut. En mode forcé, il nous aidera à convertir le type de chaîne de type numérique, le type entier int, le booléen et le type forcé. Les autres types ne peuvent pas être convertis et une erreur sera signalée.

Encore l'exemple de tout à l'heure :

class MyInfo
{
    public $a = 123;
    public function get1(bool $b)
    {
        var_dump($b);
    }
    public function get2(int $b)
    {
        var_dump($b);
    }
    public function get3(string $b)
    {
        var_dump($b);
    }
    public function get4(float $b)
    {
        var_dump($b);
    }
    public function get5(array $b)
    {
        var_dump($b);
    }
}

On passe d'abord dans all int 1

$info = new MyInfo();
$info->get1(1);
$info->get2(1);
$info->get3(1);
$info->get4(1);

Regardez le résultat imprimé, il a déjà été forcé de se convertir pour nous.

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:11:
bool(true)
/Users/yangyi/www/testPHP/3.php:19:
int(1)
/Users/yangyi/www/testPHP/3.php:26:
string(1) "1"
/Users/yangyi/www/testPHP/3.php:33:
double(1)

Continuons et passons dans la chaîne 1.23 :

$info = new MyInfo();
$info->get1(&#39;1.23&#39;);
$info->get2(&#39;1.23&#39;);
$info->get3(&#39;1.23&#39;);
$info->get4(&#39;1.23&#39;);

Regardez et imprimez le résultat. Il a également été contraint de se convertir pour nous.

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:11:
bool(true)
/Users/yangyi/www/testPHP/3.php:19:
int(1)
/Users/yangyi/www/testPHP/3.php:26:
string(4) "1.23"
/Users/yangyi/www/testPHP/3.php:33:
double(1.23)

Mais si nous ne pouvons pas forcer le paramètre à être un tableau, nous obtiendrons une erreur :

$info->get5(&#39;1.23&#39;);
 testPHP /usr/local/opt/php70/bin/php 3.php
PHP Fatal error:  Uncaught TypeError: Argument 1 passed to MyInfo::get5() must be of the type array, string given, called in /Users/yangyi/www/testPHP/3.php on line 54 and defined in /Users/yangyi/www/testPHP/3.php:37

Aurons-nous une erreur lorsque nous exécuterons ces codes en PHP5.6.11 ? Essayez-le :

$info = new MyInfo();
$info->get1(&#39;1.23&#39;);
$info->get2(&#39;1.23&#39;);
$info->get3(&#39;1.23&#39;);
$info->get4(&#39;1.23&#39;);
➜  testPHP php 3.php
PHP Catchable fatal error:  Argument 1 passed to MyInfo::get1() must be an instance of bool, string given, called in /Users/yangyi/www/testPHP/3.php on line 48 and defined in /Users/yangyi/www/testPHP/3.php on line 8

D'accord. Une erreur a été signalée directement. Même si le message d'erreur indiquait également que le type était erroné, les autres déclarations de ce type n'étaient pas prises en charge.

Mode strict

Comme mentionné précédemment, en mode forcé, cela nous aidera à forcer la conversion, mais qu'en est-il du mode strict ?

Tout d'abord, comment activer le mode strict ?

<?php
declare(strict_types=1);

Ajoutez-le simplement. De cette façon, vous entrerez en mode strict. Les paramètres doivent être conformes à la réglementation, sinon une erreur sera signalée :

Ajoutons cette phrase et exécutons. encore une fois :

<?php
declare(strict_types=1);
...
...
$info = new MyInfo();
$info->get1(&#39;1.23&#39;);
$info->get2(&#39;1.23&#39;);
$info->get3(&#39;1.23&#39;);
$info->get4(&#39;1.23&#39;);

Exécutez-le et regardez les résultats. Effectivement, une erreur est signalée directement.

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to MyInfo::get1() must be of the type boolean, string given, called in /Users/yangyi/www/testPHP/3.php on line 49 and defined in /Users/yangyi/www/testPHP/3.php:9

2. Déclaration du type de valeur de retour

Nous savons que les fonctions PHP n'ont pas de types de valeur de retour. Quel que soit le type renvoyé, c'est ce type. Le type de valeur de retour a été ajouté dans php7, et nous pouvons définir le type de valeur de retour d'une fonction.

Identique à la déclaration de type scalaire dans la mise à niveau PHP7, le type de retour peut être le suivant : bool, int, string, float, array, class.

Par exemple, si nous voulons que la valeur de retour d'une fonction soit un tableau, nous pouvons l'écrire comme ceci :

: tableau {} // deux-points + type de retour

function returnInfo ($a) : array {
    return $a;
}
var_dump(returnInfo([1,2,3]));

Ne trouvez-vous pas que c'est bizarre et incroyable ! ! !

Afficher le résultat de l'impression :

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:64:
array(3) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
}

De même, nous souhaitons renvoyer un type entier :

function returnInfo ($a) : int {
    return $a;
}
var_dump(returnInfo(&#39;1.233&#39;));

查看结果,他已经帮我们强制转换成整型了。

➜  testPHP /usr/local/opt/php70/bin/php 3.php
/Users/yangyi/www/testPHP/3.php:64:
int(1)

同样,我们可以返回一个class类型的:

public function getLogger(): Logger {
    return $this->logger;
}

默认,也是强制模式,会帮我们转换,如果,我们想使用严格模式,同样是一样的,在文件头部加上:

<?php
declare(strict_types=1);

就可以了,这样,我们规定返回值是什么类型,就必须得是这样,不然就报致命报错。

3. null合并运算符 (??)

由于日常使用中存在大量同时使用三元表达式和 isset()的情况, php7增加了一个新的语法糖 : null合并运算符 (??)

如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。

//php version = 7 
$username = $user ?? &#39;nobody&#39;;
//php  version < 7 得这样使用:
$username = isset($_GET[&#39;user&#39;]) ? $_GET[&#39;user&#39;] : &#39;nobody&#39;;

确实方便了很多。

我记得php5.3的更新中,加入了 三元运算符简写形式:

$a ?: $b

千万别和??搞混淆了!!!

$a ?: $b的意思是 $a为true时,直接返回$a, 否则返回$b

$a ?? $b的意思是 $a isset($a)为true, 且不为NULL, 就返回$a, 否则返回$b。

看例子:

$user = 0;
$username = $user ?? &#39;nobody&#39;;
echo $username;  //输出 0,因为 0 存在 且 不为NULL。
$username = $user ?: &#39;nobody&#39;;
echo $username; //输出 &#39;nobody&#39;,因为 0 为 false

4. 太空船操作符(组合比较符)

php7 中,新加入了一个比较符号:96b4fef55684b9312718d5de63fb7121 ,因为长相像太空船,所以,也叫太空船操作符。

它有啥用呢?

96b4fef55684b9312718d5de63fb7121用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1。

看例子:

<?php
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>

其实,蛮多地方可以派上用场的。

5. 通过define()定义常量数组

Array类型的常量现在可以通过 define()来定义。在 PHP5.6 中仅能通过const定义。

在php5.3中,增加了可以使用const来申明常量,替代define()函数,但是只能申明一些简单的变量。

//旧式风格:
define("XOOO", "Value");
//新式风格:
const XXOO = "Value";
//const 形式仅适用于常量,不适用于运行时才能求值的表达式:
// 正确
const XXOO = 1234;
// 错误
const XXOO = 2 * 617;

在php5.6中,又对const进行来升级,可以支持上面的运算了。

const A = 2;
const B = A + 1;

但是,一只都是在优化const,可是确把define()给搞忘记了,php 5.6申明一个数组常量,只能用const。所以,在 php7 中把 define()申明一个数组也给加上去了。

//php 7
define (&#39;AWS&#39; , [12,33,44,55]);
// php < 7
const QWE = [12,33,44,55];
echo AWS[1]; //12
echo QWE[2]; //33

至此,到php7版本,define()的功能和const就一摸一样了,所以,你随便用哪一个都可以,但是因为在class类中,什么常量是const。所以,我们就统一用const申明常量好了。

6. 匿名类

现在已经支持通过new class 来实例化一个匿名类,这可以用来替代一些用后即焚的完整类定义。

看下这个官方文档上的一个栗子:

<?php
interface Logger {
    public function log(string $msg);
}
class Application {
    private $logger;
    public function getLogger(): Logger {
         return $this->logger;
    }
    public function setLogger(Logger $logger) {
         $this->logger = $logger;
    }
}
$app = new Application;
$app->setLogger(new class implements Logger {
    public function log(string $msg) {
        echo $msg;
    }
});
var_dump($app->getLogger());
?>

我们先输出的打印的结果,显示为匿名类:

class class@anonymous#2 (0) {
}

我们来分解下,还原被偷懒的少写的代码:

class logClass implements Logger {
    public function log(string $msg) {
        echo $msg;
    }
}
$app = new Application;
$log2 = new logClass;
$app->setLogger($log2);

输出结果为:

class logClass#2 (0) {
}

虽然代码简洁了很多,但是还是有点不适应,多用用就好了。

还记得php中的匿名函数嘛?在php5.3中新增的匿名函数,结合新的,顺便复习下:

function arraysSum(array ...$arrays): array {
    return array_map(function(array $array): int {
        return array_sum($array);
    }, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));

输出结果为:

Array
(
    [0] => 6
    [1] => 15
    [2] => 24
)

7. Unicode codepoint 转译语法

ps : 由于用的少,我就直接抄官网的说明了。

这接受一个以16进制形式的 Unicode codepoint,并打印出一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的。

echo "\u{0000aa}";
echo "\u{aa}"; //省略了开头的0
echo "\u{9999}";

看下输出:

ª ª 香

我们在php5.6环境下执行下呢?会怎样:

\u{aa} \u{0000aa} \u{9999}

好吧,直接原样输出了。

8. Closure::call() 闭包

ps : 由于用的少,我就直接抄官网的说明了。

Closure::call() 现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。

<?php
class A {private $x = 1;}
// php 7之前:
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, &#39;A&#39;); // intermediate closure
echo $getX();
// PHP 7:
$getX = function() {return $this->x;};
echo $getX->call(new A);

会输出:

1
1

9. 为unserialize()提供过滤

unserialize 这个函数应该不陌生,它是php中用解开用serialize序列化的变量。

看个栗子:

<?php
$a = [1,2,3,4,5,6];
$b = serialize($a);
$c = unserialize($b);
var_dump($a, $b, $c);

打印结果为:

array(6) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
  [3] =>
  int(4)
  [4] =>
  int(5)
  [5] =>
  int(6)
}
string(54) "a:6:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;}"
array(6) {
  [0] =>
  int(1)
  [1] =>
  int(2)
  [2] =>
  int(3)
  [3] =>
  int(4)
  [4] =>
  int(5)
  [5] =>
  int(6)
}

现在php7中unserialize会变得更佳好用,它多了一个参数,用来反序列化包涵class的过滤不需要的类,变的更加安全。

unserialize($one, ["allowed_classes" => true]);
    unserialize($one, ["allowed_classes" => false]);
    unserialize($one, ["allowed_classes" => [class1,class2,class3]]);

举个例子,先序列化一个类。

class MyInfo {
        public function getMyName()
        {
                return &#39;phper&#39;;
        }
}
$phper = new MyInfo();
$one = serialize($phper);
//参数allowed_classes 设置为 true,表示允许解析class
$two = unserialize($one, ["allowed_classes" => true]);
//参数allowed_classes 设置为 false,表示不允许解析class
$three = unserialize($one, ["allowed_classes" => false]);
//不加参数。正常解析。
$four = unserialize($one);
//只允许解析 类 MyInfo1。
$five = unserialize($one, ["allowed_classes" => ["MyInfo1"]]);
//分别输出下 getMyName方法;
var_dump($one);
var_dump($two->getMyName());
var_dump($three->getMyName());
var_dump($four->getMyName());
var_dump($five->getMyName());

发现3和5直接报致命错误了:

PHP Fatal error:  main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "MyInfo" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition  in /Users/yangyi/www/php7/5.php on line 22

大致意思就是,没权限解析。

所以,我们改一下:

$three = unserialize($one, ["allowed_classes" => true]);
$five = unserialize($one, ["allowed_classes" => ["MyInfo"]]);

再输出,就正常了。

/Users/yangyi/www/php7/5.php:22:
string(17) "O:6:"MyInfo":0:{}"
/Users/yangyi/www/php7/5.php:23:
string(5) "phper"
/Users/yangyi/www/php7/5.php:24:
string(5) "phper"
/Users/yangyi/www/php7/5.php:25:
string(5) "phper"
/Users/yangyi/www/php7/5.php:26:
string(5) "phper"

发现我目前为止并没用到,并没有什么乱用,好吧,继续下一个。

10. IntlChar

ps : 由于用的少,我就直接抄官网的说明了。

新增加的 IntlChar(http://php.net/manual/zh/class.intlchar.php) 类旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。

<?php
printf(&#39;%x&#39;, IntlChar::CODEPOINT_MAX);
echo IntlChar::charName(&#39;@&#39;);
var_dump(IntlChar::ispunct(&#39;!&#39;));

以上例程会输出:

10ffff
COMMERCIAL AT
bool(true)

若要使用此类,请先安装Intl扩展

相关推荐:《PHP7新特性手册

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer