<p>類型聲明(míng)可(kě)以用于函數(shù)的參數(shù)、返回值,PHP 7.4.0 起還可(kě)以用于類的屬性,來顯性的指定需要(yào)的類型,如(rú)果預期類型在調用時(shí)不匹配,則會抛出一(yī)個 TypeError 異常。
PHP 支持各種單一(yī)類型,除了(le) resource 之外(wài),都(dōu)可(kě)以用于用戶級别類型聲明(míng)。這(zhè)個頁面包含了(le)不同類型間(jiān)的可(kě)用性變更日志以及在類型聲明(míng)中用法的文檔。
注意:
當類實現了(le)接口方法或者重新實現了(le)父級類中定義的方法時(shí),必須與上(shàng)述定義兼容。如(rú)果方法遵循方差規則,則兼容該方法。
更新日志
版本 | 說明(míng) |
---|---|
8.2.0 | 新增對 DNF 類型的支持。 |
8.2.0 | 新增對 literal 類型 true 的支持。 |
8.2.0 | 現在可(kě)以單獨使用 null 和(hé) false。 |
8.1.0 | 新增對交集類型的支持。 |
8.1.0 | 棄用 void 函數(shù)通(tōng)過引用返回。 |
8.1.0 | 新增對返回類型 never 的支持。 |
8.0.0 | 新增對 mixed 類型的支持。 |
8.0.0 | 新增對返回類型 static 的支持。 |
8.0.0 | 新增對聯合類型的支持。 |
7.2.0 | 新增對 object 類型的支持。 |
7.1.0 | 新增對 iterable 類型的支持。 |
7.1.0 | 新增對 void 類型的支持。 |
7.1.0 | 新增對可(kě)為(wèi) null 類型的支持。 |
基本類型使用說明(míng) ¶
Base types have straight forward behaviour with some minor caveats which are described in this section.
标量類型 ¶
警告
标量類型(bool、int、float、string)不支持别名。别名反而會視(shì)為(wèi)類或接口名。例如(rú),使用 boolean 作(zuò)為(wèi)類型聲明(míng),将要(yào)求值是 instanceof 類或接口 boolean,而不是類型 bool。
<?php
function test(boolean $param) {}
test(true);
?>
以上(shàng)例程在 PHP 8 中的輸出:
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
Stack trace:
#0 -(3): test(true)
#1 {main}
thrown in - on line 2
void ¶
注意:
從(cóng) PHP 8.1.0 起棄用 void 函數(shù)通(tōng)過引用返回,因為(wèi)這(zhè)樣的函數(shù)自(zì)相矛盾。在此之前調用時(shí)總是會發出如(rú)下(xià) E_NOTICE:Only variable references should be returned by reference。
<?php
function &test(): void {}
?>
Callable 類型 ¶
此類型不能(néng)用于類屬性的類型聲明(míng)。
注意: 無法指定函數(shù)的簽名。
通(tōng)過引用傳遞的參數(shù)類型 ¶
如(rú)果通(tōng)過引用傳遞的參數(shù)有類型聲明(míng),則變量的類型僅在調用函數(shù)時(shí)檢查,返回時(shí)不會檢查。這(zhè)意味着函數(shù)可(kě)以改變引用變量的類型。
示例 #1 通(tōng)過引用傳遞的參數(shù)類型
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
以上(shàng)例程的輸出類似于:
int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
Stack trace:
#0 -(9): array_baz(1)
#1 {main}
thrown in - on line 2
複合類型使用說明(míng) ¶
複合類型聲明(míng)有幾個限制,并且在編譯時(shí)執行(xíng)冗餘檢查以避免簡單的錯誤。
警告
在 PHP 8.2 之前,也就是沒引入 DNF 之前,交集類型和(hé)聯合類型不能(néng)組合使用。
聯合類型 ¶
警告
在一(yī)個聯合類型中不能(néng)同時(shí)用兩個 literal 類型 false 和(hé) true。而是使用 bool 替代。
警告
在 PHP 8.2.0 之前,由于 false 和(hé) null 不能(néng)作(zuò)為(wèi)獨立的類型使用,因此不允許僅由這(zhè)些類型組成聯合類型。這(zhè)還包括以下(xià)類型:false、false|null, 和(hé) ?false。
可(kě)為(wèi) null 類型語法糖
單個基本類型聲明(míng)可(kě)以通(tōng)過在類型前添加問(wèn)号(?)來标記可(kě)為(wèi) null。因此 ?T 和(hé) T|null 是相同的。
注意: 該語法自(zì) PHP 7.1.0 起支持,且早于完整的(generalized)聯合類型支持。
注意:
也可(kě)以通(tōng)過設置參數(shù)的參數(shù)的默認值為(wèi) null 來實現允許為(wèi) null。但(dàn)并不建議(yì)這(zhè)麽做(zuò),因為(wèi)如(rú)果在子類中更改了(le)默認值,會引發類型兼容沖突,需要(yào)将 null 類型添加到類型聲明(míng)中。
示例 #2 使參數(shù)可(kě)以為(wèi) null 的舊(jiù)方法
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
以上(shàng)例程會輸出:
object(C)#1 (0) {
}
NULL
重複冗餘的類型 ¶
為(wèi)了(le)能(néng)捕獲複合類型聲明(míng)中的簡單錯誤,不需要(yào)類加載檢測到的冗餘類型将導緻編譯時(shí)錯誤。包含:
解析出來的類型隻能(néng)出現一(yī)次。例如(rú)這(zhè)樣的類型 int|string|INT 或 Countable&Traversable&COUNTABLE 會導緻錯誤。
使用 mixed 會導緻錯誤。
對于聯合類型:
使用了(le) bool 時(shí)就不能(néng)再附帶使用 false 或者 true。
使用了(le) object 時(shí)就不能(néng)再附帶使用 class 類型。
使用了(le) iterable 時(shí),不能(néng)再附帶使用 array 和(hé) Traversable。
對于交集類型:
使用 class-type 以外(wài)的類型會導緻錯誤。
使用 self、parent 或 static 都(dōu)會導緻錯誤。
DNF 類型:
If a more generic type is used, the more restrictive one is redundant.
使用兩個相同的交集類型。
注意: 不過它不能(néng)确保類型最小化,因為(wèi)要(yào)達到這(zhè)樣的效果,還要(yào)加載使用類型的 class。
例如(rú),假設 A 和(hé) B 都(dōu)是一(yī)個類的别名, 而 A|B 仍然是有效的,哪怕它可(kě)以被簡化為(wèi) A 或 B。 同樣的,如(rú)果 B extends A {},那(nà) A|B 仍然是有效的聯合類型,盡管它可(kě)以被簡化為(wèi) A。
<?php
function foo(): int|INT {} // 不允許
function foo(): bool|false {} // 不允許
function foo(): int&Traversable {} // 不允許
function foo(): self&Traversable {} // 不允許
use A as B;
function foo(): A|B {} // 不允許 ("use" 是名稱解析的一(yī)部分)
function foo(): A&B {} // 不允許 ("use" 是名稱解析的一(yī)部分)
class_alias('X', 'Y');
function foo(): X|Y {} // 允許 (運行(xíng)時(shí)才能(néng)知道(dào)重複性)
function foo(): X&Y {} // 允許 (運行(xíng)時(shí)才能(néng)知道(dào)重複性)
?>
範例 ¶
示例 #3 基礎類類型聲明(míng)
<?php
class C {}
class D extends C {}
// 沒有繼承 C。
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
以上(shàng)例程在 PHP 8 中的輸出:
C
D
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
Stack trace:
#0 -(14): f(Object(E))
#1 {main}
thrown in - on line 8
示例 #4 基礎接口類型聲明(míng)
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// 沒有實現(implement)I。
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
以上(shàng)例程在 PHP 8 中的輸出:
C
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
Stack trace:
#0 -(13): f(Object(E))
#1 {main}
thrown in - on line 8
示例 #5 基礎返回類型聲明(míng)
<?php
function sum($a, $b): float {
return $a + $b;
}
// Note that a float will be returned.
var_dump(sum(1, 2));
?>
以上(shàng)例程會輸出:
float(3)
示例 #6 返回對象
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
以上(shàng)例程會輸出:
object(C)#1 (0) {
}
示例 #7 可(kě)為(wèi) null 參數(shù)類型聲明(míng)
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>
以上(shàng)例程會輸出:
object(C)#1 (0) {
}
NULL
示例 #8 可(kě)為(wèi) null 返回類型聲明(míng)
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>
嚴格類型 ¶
默認如(rú)果可(kě)能(néng),PHP 會強制轉化不合适的類型為(wèi)想要(yào)的标量類型。 比如(rú),參數(shù)想要(yào) string,傳入的是 int, 則會獲取 string 類型的變量。
可(kě)以按文件開(kāi)啓嚴格模式。 在嚴格模式下(xià),隻能(néng)接受完全匹配的類型,否則會抛出 TypeError。 唯一(yī)的例外(wài)是 int 值也可(kě)以傳入聲明(míng)為(wèi) float 的類型。
警告
通(tōng)過內(nèi)部函數(shù)調用函數(shù)時(shí),不會受 strict_types 聲明(míng)影響。
要(yào)開(kāi)啓嚴格模式,使用 declare 開(kāi)啓 strict_types:
注意:
文件開(kāi)啓嚴格類型後的內(nèi)部調用函數(shù)将應用嚴格類型, 而不是在聲明(míng)函數(shù)的文件內(nèi)開(kāi)啓。 如(rú)果文件沒有聲明(míng)開(kāi)啓嚴格類型,而被調用的函數(shù)所在文件有嚴格類型聲明(míng), 那(nà)将遵循調用者的設置(開(kāi)啓類型強制轉化), 值也會強制轉化。
注意:
隻有為(wèi)标量類型的聲明(míng)開(kāi)啓嚴格類型。
示例 #9 參數(shù)值的嚴格類型
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
以上(shàng)例程在 PHP 8 中的輸出:
int(3)
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
Stack trace:
#0 -(9): sum(1.5, 2.5)
#1 {main}
thrown in - on line 4
示例 #10 參數(shù)值的類型強制轉化
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// 以下(xià)會強制轉化為(wèi)整型,注意以下(xià)內(nèi)容輸出!
var_dump(sum(1.5, 2.5));
?>
以上(shàng)例程會輸出:
int(3)
int(3)
示例 #11 返回值的嚴格類型
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
以上(shàng)例程會輸出:
int(3)
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
Stack trace:
#0 -(9): sum(1, 2.5)
#1 {main}
thrown in - on line 5</p>
網站建設開(kāi)發|APP設計開(kāi)發|小程序建設開(kāi)發