Heim >Backend-Entwicklung >PHP-Tutorial >Detaillierte Erläuterung des Beispielcodes der PHP7-Skalartypdeklaration RFC
1. Zusammenfassung
Dieser RFC empfiehlt das Hinzufügen von 4 neuen Skalartypdeklarationen: int, float, string und bool. Diese Typdeklarationen werden konsistent mit dem ursprünglichen Mechanismus von PHP verwendet. Der RFC empfiehlt außerdem, jeder PHP-Datei eine neue optionale Anweisung (declare(strict_type=1);) hinzuzufügen, damit alle Funktionsaufrufe und Anweisungsrückgaben in derselben PHP-Datei eine „streng eingeschränkte“ Anweisungsprüfung haben. Darüber hinaus wird nach dem Aktivieren strenger Typbeschränkungen beim Aufrufen von Erweiterungen oder integrierten PHP-Funktionen ein Fehler der Ebene E_RECOVERABLE_ERROR generiert, wenn die Parameteranalyse fehlschlägt. Mit diesen beiden Funktionen hofft der RFC, dass das Schreiben von PHP genauer und dokumentierter wird.
2. Details
Skalare Typdeklaration:
Kein Neues hinzugefügt Das reservierte Wort. Int, Float, String und Bool werden als Typdeklarationen erkannt und dürfen nicht als Namen für Klassen/Schnittstellen/Eigenschaften usw. verwendet werden. Neue Skalartypdeklaration für Benutzer, implementiert über die interne Fast Parameter Parsing API.
strict_types/declare() Direktive
Standardmäßig befinden sich alle PHP-Dateien im schwachen Typprüfungsmodus. Die neue Declare-Direktive gibt den Wert von strict_types an (1 oder 0). 1 gibt den strikten Typprüfungsmodus an, der für Funktionsaufrufe und Rückgabeanweisungen gilt.
declare(strict_types=1) muss die erste Anweisung der Datei sein. Wenn diese Anweisung an anderer Stelle in der Datei vorkommt, wird ein Kompilierungsfehler generiert und der Blockmodus wird ausdrücklich verboten.
ähnelt der Encoding-Direktive, aber im Gegensatz zur Ticks-Direktive wirkt sich die strict_types-Direktive nur auf die angegebenen Dateien und Willen aus hat keinen Einfluss auf andere darin enthaltene Dateien (über include usw.). Diese Direktive wird zur Laufzeit kompiliert und kann nicht geändert werden. Die Funktionsweise besteht darin, im Opcode ein Flag zu setzen, damit Funktionsaufrufe und Rückgabetypprüfungen den Typbeschränkungen entsprechen.
Parametertypdeklaration
Diese Direktive betrifft alle Funktionsaufrufe, zum Beispiel (strenger Verifizierungsmodus):
<?php declare(strict_types=1); foo(); // strictly type-checked functioncall function foobar() { foo(); // strictly type-checked function call } class baz { function foobar() { foo(); // strictly type-checked function call } }
Vergleich (schwacher Validierungsmodus)
<?php foo(); // weakly type-checked function call function foobar() { foo(); // weakly type-checked function call } class baz { function foobar() { foo(); // weakly type-checked function call } } ?>
Rückgabetypdeklaration: Die
-Anweisung wirkt sich auf dieselben Rückgabetypen aus aller Funktionen unter der Datei. Zum Beispiel (strenger Validierungsmodus):
<?php declare(strict_types=1); function foobar(): int { return 1.0; // strictly type-checked return } class baz { function foobar(): int { return 1.0; // strictly type-checked return }} ?>
<?php function foobar(): int { return 1.0; // weakly type-checked return } class baz { function foobar(): int { return 1.0; // weakly type-checked return }} ?>
Schwaches Typprüfungsverhalten:
一个弱类型校验的函数调用,和PHP7之前的PHP版本是一致的(包括拓展和PHP内置函数)。通常,弱类型校验规则对于新的标量类型声明的处理是相同的,但是,唯一的例外是对NULL的处理。为了和我们现有类、调用、数组的类型声明保持一致,NULL不是默认的,除非它作为一个参数并且被显式赋值为NULL。
为了给不熟悉PHP现有的弱标量参数类型规则的读者,提供简短的总结。表格展示不同类型能够接受和转换的标量类型声明,NULL、arrays和resource不能接受标量类型声明,因此不在表格内。
*只有范围在PHP_INT_MIN和PHP_INT_MAX内的non-NaN float类型可以接受。(PHP7新增,可查看ZPP Failure on Overflow RFC)
?Non-numeric型字符串不被接受,Numeric型字符串跟随字符串的,也可以被接受,但是会产生一个notice。
?仅当它有toString方法时可以。
严格类型校验行为:
严格的类型校验调用拓展或者PHP内置函数,会改变zend_parse_parameters的行为。特别注意,失败的时候,它会产生E_RECOVERABLE_ERROR而不是E_WARNING。它遵循严格类型校验规则,而不是传统的弱类型校验规则。严格类型校验规则是非常直接的:只有当类型和指定类型声明匹配,它才会接受,否则拒绝。
有一个例外的是,宽泛类型转换是允许int变为float的,也就是说参数如果被声明为float类型,但是它仍然可以接受int参数。
<?php declare(strict_types=1); function add(float $a, float $b): float { return $a + $b;} add(1, 2); // float(3) ?>
在这种场景下,我们传递一个int参数给到定义接受float的函数,这个参数将会被转换为float。除此之外的转换,都是不被允许的。
三、例子:
让我们创建一个函数,让2个数相加。
add.php <?php function add(int $a, int $b): int { return $a + $b;} ?>
如果在分开的文件,我们可以调用add函数通过弱类型的方式
<?php require "add.php"; var_dump(add(1,2)); // int(3) // floats are truncated by default var_dump(add(1.5,2.5)); // int(3) //strings convert if there's a number part var_dump(add("1","2")); // int(3) ?>
默认情况下,弱类型声明允许使用转换,传递进去的值会被转换。
<?php require "add.php"; var_dump(add("1foo", "2")); // int(3) // Notice: A non well formed numeric value encountered
但是,通过可选择指令declare开启严格类型校验后,在这个场景下,相同的调用将会失败。
<?php declare(strict_types=1); require "add.php"; var_dump(add(1,2)); // int(3) var_dump(add(1.5,2.5)); // int(3) // Catchable fatal error: Argument 1 passed to add() must be of the type integer, float given
指令影响同一个文件下的所有函数调用,不管这个被调函数是否在这个文件内定义的,都会采用严格类型校验模式。
<?php declare(strict_types=1); $foo = substr(52,1); // Catchable fatal error: substr() expects parameter 1 to be string, integer given
标量类型声明也可以用于返回值的严格类型校验:
<?php function foobar(): int { return 1.0; } var_dump(foobar());// int(1)
在弱类型模式下,float被转为integer。
<?php declare(strict_types=1); function foobar(): int { return 1.0; } var_dump(foobar()); //Catchable fatal error: Return value of foobar() must be of the type integer,float returned
四、背景和理论基础
历史
PHP从PHP5.0开始已经有对支持class和interface参数类型声明,PHP5.1支持array以及PHP5.4支持callable。这些类型声明让PHP在执行的时候传入正确的参数,让函数签名具有更多的信息。
先前曾经想添加标量类型声明,例如Scalar Type Hints with Casts RFC,因为各种原因失败了:
(1)类型转换和校验机制,对于拓展和PHP内置函数不匹配。
(2)它遵循一个弱类型方法。
(3)它的“严格”弱类型修改尝试,既没有满足严格类型的粉丝期望,也没有满足弱类型的粉丝。
这个RFC尝试解决全部问题。
弱类型和强类型
在现代编程语言的实际应用中,有三种主要的方法去检查参数和返回值的类型:
(1)全严格类型检查(也就是不会有类型转换发生)。例如F#、GO、Haskell、Rust和Facebook的Hack的用法。
(2)广泛原始类型检查(“安全”的类型转换会发生)。例如Java、D和Pascal。他们允许广泛原始类型转换(隐式转换),也就是说,一个8-bit的integer可以根据函数参数需要,被隐形转换为一个16-bit的integer,而且int也可以被转换为float的浮点数。其他类型的隐式转换则不被允许。
(3)弱类型检查(允许所有类型转换,可能会引起警告),它被有限制地使用在C、C#、C++和Visual Basic中。它们尝试尽可能“不失败”,完成一次转换。
PHP在zend_parse_parameters的标量内部处理机制是采用了弱类型模式。PHP的对象处理机制采用了广泛类型检查方式,并不追求精确匹配和转换。
每个方法各有其优缺点。
这个提案中,默认采用弱类型校验机制,同时追加一个开关,允许转换为广泛类型校验机制(也就是严格类型校验机制)。
Warum beides unterstützen?
Bisher benötigen die meisten Befürworter skalarer Typdeklarationen Unterstützung sowohl für strikte Typprüfung als auch für schwache Typisierung. Die Verifizierung erfordert nicht nur Unterstützung Unterstützen Sie einen von ihnen. Dieser RFC macht die schwache Typprüfung zum Standardverhalten und fügt eine optionale Anweisung zur Verwendung einer strengen Typprüfung hinzu (in derselben Datei). Es gibt viele Gründe für diese Wahl.
Ein großer Teil der PHP-Community scheint Quan zu mögen Statischer -Typ. Das Hinzufügen einer strengen Typprüfung zu Skalartypdeklarationen führt jedoch zu einigen Problemen:
(1) was offensichtliche Inkonsistenzen verursacht: Erweiterungen und PHP erstellt -in-Funktionen verwenden eine schwache Typprüfung für Skalartypparameter, die PHP-Funktionen des Benutzers verwenden jedoch eine strikte Typprüfung.
(2) Eine beträchtliche Anzahl von Menschen bevorzugen eine schwache Typprüfung und sind mit diesem Vorschlag nicht einverstanden und blockieren möglicherweise seine Implementierung .
(3) Bereits vorhandener Code verwendet die schwachen PHP-Typen, die betroffen sein werden. Wenn Funktionen zum Hinzufügen skalarer Typdeklarationen zu Parametern erforderlich sind, erhöht dies die Komplexität vorhandener Codebasen erheblich, insbesondere für Bibliotheksdateien.
Hier gibt es immer noch einige Leute, die schwache Typprüfung mögen. Allerdings führt sowohl das Hinzufügen strenger Typprüfungsdeklarationen als auch das Hinzufügen schwacher Typprüfungsdeklarationen zu einigen Problemen:
(1) Die meisten Leute, die Wenn Sie eine strikte Typprüfung bevorzugen, wird dieser Vorschlag nicht gefallen und seine Implementierung blockieren.
(2) Begrenzen Sie die Möglichkeiten für statische Analysen. (Vielleicht bedeutet es Optimierungsmöglichkeiten)
(3) Es werden einige Datenverlustfehler bei der automatischen Typkonvertierung ausgeblendet.
Die dritte Lösung wurde vorgeschlagen, die darin besteht, Syntax hinzuzufügen, um zwischen schwacher Typ- und strenger Typdeklaration zu unterscheiden. Es wird auch einige Probleme mit sich bringen:
(1) Menschen, die schwache Typen und strenge Typprüfungen nicht mögen, werden in die Bibliothek gezwungen als streng typisiert oder schwach typisiert definiert werden, werden separat behandelt.
(2) Ebenso wie das Hinzufügen strikter Deklarationen ist dies auch nicht mit der Erweiterung der ursprünglichen schwachen Typimplementierung und der von PHP integrierten Version vereinbar. in Funktionen.
Um die durch diese drei Lösungen verursachten Probleme zu lösen, schlägt dieser RFC eine vierte Lösung vor: Jede Datei ist streng definiert Oder schwach Typprüfung. Es bringt die folgenden Vorteile:
(1) Die Leute können die Typprüfung wählen, die zu ihnen passt, das heißt, ich hoffe, dieses Schema um sowohl die strengen als auch die schwachen Typprüfungslager zu erfüllen.
(2) Die API wird nicht gezwungen, sich an ein bestimmtes Typdeklarationsmuster anzupassen.
(3) Da die Datei standardmäßig ein schwaches Typprüfungsschema verwendet, kann die vorhandene Codebasis geändert werden, ohne den Code zu zerstören Struktur. Fügen Sie in diesem Fall eine Skalartypdeklaration hinzu. Es ist auch möglich, dass die Codebasis Typdeklarationen inkrementell oder nur für bestimmte Module hinzufügt.
(4) Zur Definition einer Skalartypdeklaration ist nur eine einzige Syntax erforderlich.
(5) Personen, die eine strenge Typprüfung bevorzugen, verwenden diese Funktion normalerweise nicht nur in benutzerdefinierten Funktionen, sondern auch Wird auch in verwendet Erweiterungen und integrierte PHP-Funktionen. Mit anderen Worten: PHP-Benutzer erhalten einen einheitlichen Mechanismus ohne den Widerspruch einer strikten Skalardeklaration.
(6) Im strikten Typprüfungsmodus die Fehlerstufe von Typprüfungsfehlern, die durch Erweiterung und integrierte PHP-Funktionen erzeugt werden, Es stimmt mit dem von der benutzerdefinierten Funktion generierten überein, nämlich E_RECOVERABLE_ERROR.
(7) Es ermöglicht die nahtlose Integration von streng typisiertem und schwach typisiertem Code in eine einzige Codebasis.
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Beispielcodes der PHP7-Skalartypdeklaration RFC. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!