首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 型別約束完全指南:原生支援與 SPL Types 擴展

     編輯:PHP 相關知識

PHP 7/8 原生型別宣告 (標量 + 復合)

PHP 7.0 引入標量型別宣告,PHP 8.0 補全聯集型別,現代 PHP 已支援完整的型別系統:

支援的型別分類

類別型別PHP 版本說明
標量int7.0整數
float7.0浮點數
bool7.0布林值
string7.0字串
復合array5.1陣列
callable5.4可呼叫物件
object7.2任意物件
類/介面ClassName / InterfaceName5.0具體類或介面
特殊void7.1無返回值 (僅返回型別)
never8.1永不返回 (拋出例外/死循環)
mixed8.0任意型別 (等同無宣告)
聯集Type1|Type28.0多型別任一 (如 int|string)
交集Type1&Type28.1同時滿足 (如 Countable&Iterator)
可為 null?Type / Type|null7.1 / 8.0允許 null 值

嚴格模式 vs 弱類型模式

<?php
// 檔案最頂部宣告 (必須是第一行程式碼)
declare(strict_types=1);

function add(int $a, int $b): int {
    return $a + $b;
}

// 嚴格模式
add(1, 2);     // 3 ✓
add('1', '2'); // TypeError ✗ (弱模式下會自動轉型為 3)
add(1.5, 2.5); // TypeError ✗
  • strict_types=1:強制精確型別匹配,不自動轉型。建議所有新專案啟用。
  • strict_types=0 (預設):弱模式,允許兼容轉型 (如 "123" → int)。
  • 模式由「呼叫端」檔案宣告決定,非函數定義檔案。

參數預設值與可為 null

<?php
function greet(string $name = 'Guest'): string {
    return "Hello, $name";
}
function greetNullable(?string $name = null): string {
    return $name ? "Hello, $name" : 'Hello, Guest';
}
function greetUnion(string|null $name = null): string { // PHP 8.0+
    return $name ? "Hello, $name" : 'Hello, Guest';
}

返回型別宣告

<?php
function getUser(int $id): array|User|null { // PHP 8.0 聯集型別
    if ($id < 0) return null;
    if ($id === 0) return ['id' => 0, 'name' => 'Guest'];
    return new User($id);
}

class User {
    public function __construct(public int $id, public string $name) {}
}

SPL Types 擴展:運行時標量物件包裝 (PECL)

若需在 PHP 5 時代或特殊場景下對標量進行強型別約束,可安裝 pecl install SPL_Types。

<?php
$int = new SplInt(94);

try {
    $int = 'Try to cast a string'; // 拋出 UnexpectedValueException
} catch (UnexpectedValueException $e) {
    echo $e->getMessage() . PHP_EOL; // Value not an integer
}

echo $int . PHP_EOL; // 94 (物件轉字串自動調用 __toString)

可用類別:SplInt、SplFloat、SplBool、SplString、SplEnum。

⚠️ 生產環境謹慎使用

  • 性能開銷:物件包裝比原生標量慢。
  • 靈活度降低:失去 PHP 動態語言優勢。
  • 相依 PECL 擴展:部署複雜度增加,兼容性風險。
  • 現代 PHP (7.1+) 完全不需要,原生型別宣告足夠強大且零成本。

最佳實踐總結

  1. 所有新專案啟用 declare(strict_types=1);
  2. 盡可能為所有函數/方法添加參數與返回型別宣告。
  3. 善用聯集型別 Type1|Type2 表達多態參數。
  4. 介面優於具體類:參數型別宣告為介面 (如 LoggerInterface) 而非實現類。
  5. 避免過度設計:簡單腳本、快速原型可暫不加型別。
  6. 配合靜態分析工具:PHPStan、Psalm、Laravel Pint 發現型別錯誤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved