Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der neuen Funktionen in PHP7.0 (Beispiel)

Detaillierte Erläuterung der neuen Funktionen in PHP7.0 (Beispiel)

藏色散人
藏色散人nach vorne
2019-03-20 13:56:424834Durchsuche


Detaillierte Erläuterung der neuen Funktionen in PHP7.0 (Beispiel)

Dieser Artikel dient hauptsächlich der detaillierten Analyse der neuen Funktionen von PHP7.0.

1. Leistung und zugrunde liegende Schicht

PHP7 ist doppelt so schnell wie PHP5.6

Die bedeutendste Änderung von php7 Es stellt eine enorme Leistungsverbesserung dar und ähnelt der von Facebook entwickelten PHP-Ausführungs-Engine HHVM. Im WordPress-Benchmark-Leistungstest ist die Geschwindigkeit zwei- bis dreimal schneller als bei Version 5.6, was den Speicherverbrauch erheblich reduziert. PHP7 hat auch einige Änderungen in der Sprache, wie das Hinzufügen von Rückgabetypdeklarationen und das Hinzufügen einiger neuer reservierter Schlüsselwörter. Aus Sicherheitsgründen wurde der abgesicherte PHP-Modus entfernt, magische Anführungszeichen hinzugefügt usw. Darüber hinaus unterstützt die neue Version auch 64-Bit und enthält die neueste Version der Zend-Engine.

Testen Sie es

Ein sehr einfaches Beispiel: Generieren Sie ein Array mit 600.000 Elementen und ermitteln Sie, ob der Schlüssel vorhanden ist, indem Sie nach dem Schlüssel suchen.

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

Wir haben die Leistung jeweils auf PHP5.6.11 und PHP7.0.4 getestet.

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

Im Durchschnitt der drei Zeiten beträgt die Benutzernutzung etwa 0,65 Sekunden, die Systemnutzung 0,06 Sekunden und die CPU-Rate 67 %. Insgesamt etwa 1 Sekunde.

Sehen Sie sich die Situation von PHP7 an

➜  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

Im Vergleich dazu sank die Benutzernutzungszeit um etwa 20 %, die Systemnutzungszeit um 70 % und die CPU-Auslastung lag bei bis zu 98 %. Die Gesamtzeit verkürzt sich auf. 0,5 Sekunden.

Bei diesem Beispiel verdoppelt sich die Effizienz. Eigentlich nicht schlecht.

Sehen Sie sich ein anderes Beispiel an. Außerdem wird ein Array mit 600.000 Elementen generiert, um herauszufinden, ob ein Wert vorhanden ist.

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

Schauen Sie sich zuerst PHP5.6.11 an.

➜  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

Dann schauen Sie sich PHP7.0.4 an.

➜  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

Es ist offensichtlich, dass es mehr als sechsmal schneller ist. scharf.

2. Neue Funktionen

Mehr Skalartypdeklarationen

Es gibt jetzt zwei Modi für Skalare: Durchsetzung (Standard) und strikter Modus. Die folgenden Typparameter sind jetzt verfügbar (entweder im erzwungenen oder strikten Modus): string, int, float und bool. Sie erweitern andere in PHP5 eingeführte Typen: Klassennamen, Schnittstellen, Arrays und Callback-Typen. In der alten Version konnten Funktionsparameterdeklarationen nur (Array $arr), (CLassName $obj) usw. lauten. Grundtypen wie Int, String usw. konnten nicht deklariert werden.

Wie verstehst du es? Wenn wir in Versionen vor PHP7 den Parametertyp einer Funktion einschränken möchten, gibt es nur zwei Typen: Array oder Klasse.

Vor php7:

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

Wir möchten den ersten Parameter von getInfo auf ein Array beschränken, damit wir vor dem Parameter $a ein Array hinzufügen können. zu erklären.

In ähnlicher Weise möchten wir, dass der Parameter von getClass eine Klasse ist, also verwenden wir den Klassennamen dieser Klasse, um sie für die obligatorische Verwendung zu deklarieren.

Vor PHP7 konnten nur diese beiden Skalare verwendet werden.

Lassen Sie es uns verwenden:

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

Wir befolgen die Vorschriften, übergeben das Array als ersten Parameter und natürlich wird das Ergebnis normal gedruckt:

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

Wenn wir es tun Wenn Sie die Vorschriften nicht installieren, wird ein bekannter Fehler gemeldet:

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

Fehler gemeldet:

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

Das Gleiche gilt für die Verwendung der Klasse:

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

Ausgabe Ergebnis:

➜  testPHP php 3.php
int(123)

In ähnlicher Weise übergeben wir Wenn Sie andere Parameter eingeben, wird ein Fehler gemeldet:

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

Kehren wir zum PHP7-Upgrade zurück, das die Skalartypen erweitert und bool, int hinzugefügt hat , string und float.

php7 verfügt über zwei Modi: den obligatorischen (Standard) und den strengen Modus.

Erzwungener Modus

Der erzwungene Modus ist der Standardmodus. Im erzwungenen Modus können wir den numerischen Typ String-Typ, den Integer-Typ Int, den Bool-Typ und den erzwungenen Typ konvertieren. Andere Typen können nicht konvertiert werden und es wird ein Fehler gemeldet.

Immer noch das Beispiel gerade:

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);
    }
}

Wir übergeben zuerst all int 1

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

um das gedruckte Ergebnis zu sehen, es wurde bereits für uns zur Konvertierung gezwungen.

➜  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)

Machen wir weiter und übergeben String 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;);

Schauen Sie sich das Ergebnis an und drucken Sie es aus. Es wurde auch für uns zur Umstellung gezwungen.

➜  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)

Aber wenn wir nicht erzwingen können, dass der Parameter ein Array ist, erhalten wir eine Fehlermeldung:

$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

Erhalten wir eine Fehlermeldung, wenn wir diese Codes in PHP5.6.11 ausführen? Probieren Sie es aus:

$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

Okay. Obwohl in der Fehlermeldung auch angegeben wurde, dass der Typ falsch sei, wurden andere Deklarationen dieser Typen nicht unterstützt.

Strikter Modus

Wie bereits erwähnt, hilft es uns im erzwungenen Modus, die Konvertierung zu erzwingen, aber was ist mit dem strikten Modus?

Zunächst einmal: Wie aktiviert man den strikten Modus? Fügen Sie einfach

<?php
declare(strict_types=1);

hinzu. Auf diese Weise gelangen Sie in den strikten Modus. Die Parameter müssen den Vorschriften entsprechen, sonst wird ein Fehler gemeldet:

Lassen Sie uns diesen Satz hinzufügen und erneut ausführen:

<?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;);

Führen Sie es aus und sehen Sie sich die Ergebnisse an. Tatsächlich wird direkt ein Fehler gemeldet.

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. Rückgabewerttypdeklaration

Wir wissen, dass PHP-Funktionen keine Rückgabewerttypen haben. Der Rückgabewerttyp wurde in PHP7 hinzugefügt, und wir können den Rückgabewerttyp einer Funktion definieren.

Wie bei der Skalartypdeklaration beim PHP7-Upgrade kann der Rückgabetyp der folgende sein: bool, int, string, float, array, class.

Wenn wir beispielsweise möchten, dass der Rückgabewert einer Funktion ein Array ist, können wir es so schreiben:

: array {} // Doppelpunkt + Rückgabetyp

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

Finden Sie es nicht seltsam und unglaublich? ! !

Druckergebnis anzeigen:

➜  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)
}

In ähnlicher Weise möchten wir einen Ganzzahltyp zurückgeben:

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新特性手册

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der neuen Funktionen in PHP7.0 (Beispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:zybuluo.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen