> PHP 8.0.0 已經正式發布了,這個對于PHPer無疑是一個令人振奮的消息。它包含了很多新功能與優化項, 包括命名參數、聯合類型、注解、構造器屬性提升、`match `表達式、`nullsafe `運算符、`JIT`,并改進了類型系統、錯誤處理、語法一致性。
## 最人性化的特性:命名參數、聯合類型、`mixed`類型
這幾個新特性讓PHP在強類型方面進一步完善,而且對PHPDoc的注釋依賴越來越弱,代碼即文檔的好處是開發者最頭疼的事情終于有辦法可以偷懶了。
### 命名參數
命名參數可以讓函數或者方法的調用更加清晰直觀,對于如下的函數定義
```
function foo(string $a, string $b, ?string $c = null, ?string $d = null)
{ /* … */ }
```
你可以通過下面的方式傳入參數進行調用
```
foo(
b: 'value b',
a: 'value a',
d: 'value d',
);
```
最大的好處是傳入參數的順序是和定義無關的,而且還可以混合傳參(但不建議)。
### 聯合類型
相對于以前的 PHPDoc 聲明類型的組合, 現在可以用原生支持的聯合類型聲明取而代之,可在實際運行中驗證。
PHP7
```
class Number {
/** @var int|float */
private $number;
/**
* @param float|int $number
*/
public function __construct($number) {
$this->number = $number;
}
}
new Number('NaN'); // Ok
```
PHP8
```
class Number {
public function __construct(
private int|float $number
) {}
}
new Number('NaN'); // TypeError
```
### 新的 `mixed`類型
`mixed`本身是以下類型之一:
* `array`
* `bool`
* `callable`
* `int`
* `float`
* `null`
* `object`
* `resource`
* `string`
注意,`mixed`也可以用作參數或屬性類型,而不僅僅是返回類型。
另外由于`mixed`已經包含`null`,因此不允許將其設置為`nullable`。以下內容將觸發錯誤:
~~~
// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function bar(): ?mixed {}
~~~
## 最具貢獻的特性:`JIT`
JIT作為PHP底層編譯引擎,對于PHP8的性能貢獻是非常之大,不過對于常規WEB應用來說,優勢不明顯,但仍然是非常的高大上特性,是PHP8的扛鼎之作。
PHP 8 引入了兩個即時編譯引擎。 Tracing JIT 在兩個中更有潛力,它在綜合基準測試中顯示了三倍的性能, 并在某些長時間運行的程序中顯示了 1.5-2 倍的性能改進。 典型的應用性能則和 PHP 7.4 不相上下。
### 關于 JIT 對 PHP 8 性能的貢獻

## 最實用的特性:構造器屬性提升、`Nullsafe`運算符、`str_contains()`、 `str_starts_with()`、 `str_ends_with()`
### 構造器屬性提升
這個新的語法糖來用來創建值對象或數據傳輸對象。不用為類屬性和構造函數指定它們,PHP 現在可以將它們合并為一個。
代替如下代碼:
```
class Money
{
public Currency $currency;
public int $amount;
public function __construct(
Currency $currency,
int $amount,
) {
$this->currency = $currency;
$this->amount = $amount;
}
}
```
你可以這樣做:
```
class Money
{
public function __construct(
public Currency $currency,
public int $amount,
) {}
}
```
### `nullsafe`運算符
現在可以用新的 nullsafe 運算符鏈式調用,而不需要條件檢查 null。 如果鏈條中的一個元素失敗了,整個鏈條會中止并認定為 Null。
```
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
```
簡化為一行代碼
```
$country = $session?->user?->getAddress()?->country;
```
確實是有點酷
### `str_contains()`、`str_starts_with()`和`str_ends_with()`函數
有些人可能會說它早就該有了,但我們終于不必再依賴`strpos()` 來知道字符串是否包含另一個字符串了。
代替如下:
```
if (strpos('string with lots of words', 'words') !== false) { /* … */ }
```
你可以這樣做
```
if (str_contains('string with lots of words', 'words')) { /* … */ }
```
感覺大多數場景應該是不需要使用`strpos`了吧,外兩個早就應該有了,`str_starts_with()`和`str_ends_with()`這兩個函數現在能省事不少。
~~~
str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true
~~~
## 最具潛力的特性:注解、`Match`表達式、`WeakMap`
### 注解
現在可以用原生的PHP語法來使用結構化的元數據,而不需要再依賴PHPDoc解析,性能也隨之提升。之前定義注解路由可能需要使用:
```
class PostsController
{
/**
* @Route("/api/posts/{id}", methods={"GET"})
*/
public function get($id) { /* ... */ }
}
```
現在你可以直接用PHP的注解語法來定義,并通過反射直接獲取
```
class PostsController
{
#[Route("/api/posts/{id}", methods: ["GET"])]
public function get($id) { /* ... */ }
}
```
### `Match`表達式
你可以稱它為switch表達式的大哥:match可以返回值,不需要break語句,可以組合條件,使用嚴格的類型比較,并且不執行任何類型的強制。
如下所示:
```
$result = match($input) {
0 => "hello",
'1', '2', '3' => "world",
};
```
### WeakMap
`WeakMap`保留對對象的引用,這些引用不會阻止這些對象被垃圾回收。
以 ORM 為例,它們通常實現緩存,這些緩存保存對實體類的引用,以提高實體之間的關系性能。這些實體對象不能被垃圾回收,只要此緩存具有對它們的引用,即使緩存是唯一引用它們的對象。
如果此緩存層使用弱引用和映射代替,PHP 將垃圾收集這些對象當再沒有別的引用他們了。特別是在 ORM 的情況下,它可以管理請求中的數百個,如果不是數千個實體;weak maps可以提供更好、更資源友好的處理這些對象的方法。
下面是weak maps的示例:
```
class Foo
{
private WeakMap $cache;
public function getSomethingWithCaching(object $obj): object
{
return $this->cache[$obj]
??= $this->computeSomethingExpensive($obj);
}
}
```
## 其它特性
### 0 == 'foobar' 終于返回了`false`
我們知道在PHP7里面
```
0 == 'foobar' // 返回true
```
現在終于看起來更比較符合邏輯了
```
0 == 'foobar' // 返回false
```
### 可以在對象上使用`::class`
一個小而有用的新特性:現在可以對對象使用`::class`,它的工作方式與 `get_class()` 相同。
```
$foo = new Foo();
var_dump($foo::class);
```
### traits 中的抽象方法改進
Traits 可以指定抽象方法,這些方法必須由使用它們的類實現。在PHP8,必須保持一致的方法定義,包括參數類型和返回類型。
```
trait MyTrait {
abstract private function neededByTheTrait(): string;
public function doSomething() {
return strlen($this->neededByTheTrait());
}
}
class TraitUser {
use MyTrait;
// This is allowed:
private function neededByTheTrait(): string { }
// This is forbidden (incorrect return type)
private function neededByTheTrait(): stdClass { }
// This is forbidden (non-static changed to static)
private static function neededByTheTrait(): string { }
}
```
- 值得升級到5.1的18個理由
- 5.1.7版本新特性
- JSON字段類型在ORM中的使用
- 文件下載響應對象
- 教你使用5.1的數組對象查詢
- 模型三大利器之一:搜索器
- 在ThinkPHP中使用Yaconf
- 掌握命令行的表格輸出
- 5.1.25查詢參數綁定的改進
- ThinkPHP安全規范指引
- 巧用數據集的排序功能實現統計排序
- think-orm ——基于5.1的獨立ORM庫
- think-template——基于ThinkPHP的獨立模板引擎
- ThinkPHP5.1.26版本發布——修正版本,包含安全更新
- ThinkPHP5.0和3.2再發安全更新
- 官宣:ThinkPHP發布首個LTS版本
- 你真的了解Db類和模型的正確使用姿勢么?
- 如何更有效的記錄和管理日志
- 模型三大利器之二:修改器
- ThinkPHP5.1.28版本發布——修正上一版本問題,改進關聯查詢
- 模型三大利器之三:獲取器
- API版本控制的幾種思路
- ThinkPHP5.2第一個Beta版本發布測試
- 讓你少犯錯的數據查詢基本原則
- ThinkPHP發布5.1.29版本——常規更新
- 這15個好習慣讓你更容易升級到5.2
- 如何有效提高ThinkPHP的應用性能
- 讓你提高開發效率的查詢技巧
- 模型關聯查詢不完全指南
- 5.2發布Beta2版本——統一和精簡大量用法
- ThinkPHP發布5.1.30版本——支持微秒時間字段寫入
- ThinkPHP的數據緩存使用
- ThinkPHP5.2安裝及入口文件
- ThinkPHP榮獲2018 年度最受歡迎中國開源開發框架第1名
- 5.1路由使用心得技巧
- ThinkPHP5.*版本發布安全更新
- ThinkPHP項目及代碼規范指北
- 5.2版本的設計規范指導
- ThinkPHP5.1.32版本發布——圣誕快樂
- 利用Trait特性給模型增加樂觀鎖功能
- 5.2數據庫和模型的變化(摘要)
- ThinkPHP模板引擎實現和常見問題
- ThinkPHP5.0.24版本發布——安全更新
- 不忘初心,方得始終——ThinkPHP十三周年報告
- ThinkPHP5+相關資源匯總
- 異步社區ThinkPHP周年慶專享優惠活動
- 5.2路由的調整和改進
- ThinkPHP發布5.1.33版本——包含安全更新
- ThinkPHP擴展開發指南
- ThinkPHP發布5.2Beta3版本
- ThinkPHP發布5.1.34版本——喜迎新年
- ThinkPHP發布5.2RC1版本
- ThinkPHP發布5.1.35版本——常規更新
- 5.2配置類的調整
- 5.2時間查詢的改進和優化
- 5.2RC版本升級不完全指導(僅供學習參考)
- ThinkPHP5.2版本正式變更為6.0版本
- ThinkPHP百度云云虛擬主機專享免費活動
- 事件系統以及查詢事件、模型事件的使用
- ThinkPHP6.0RC2版本發布——架構升級、精簡核心
- ThinkPHP5.1.36LTS版本發布——常規更新
- 新版Session和Cookie設計變化
- ThinkPHP5.1.37版本發布——常規更新
- ThinkPHP6.0RC3版本發布——細節完善,體驗優化
- 6.0中間件使用詳解
- Composer各大廠商鏡像地址
- ThinkPHP6.0發布計劃公告
- 「ThinkPHP開發者周刊」招募志愿者
- ThinkPHP6.0日志變化
- ThinkPHP5.1.38版本發布——常規更新
- ThinkPHP6.0RC4版本發布——ORM獨立,日志多通道支持
- ThinkORM2.0開發指南上線
- ThinkPHP6.0RC5版本發布——多應用模式獨立,中間件機制調整
- ThinkPHP6.0版本發布——程序員節福利
- ThinkPHP5.1.39LTS版本發布——常規更新
- ThinkPHP6.0.1版本發布——圣誕快樂!
- 回顧2019,展望2020!
- ThinkPHPV6.0.2版本發布——2020新春快樂!
- 周年福利系列:Swoole合作優惠
- 億速云成為ThinkPHPV6.0獨家贊助發布商??
- 新冠疫情工具和限免資源專題(保持更新中)
- 周年福利系列:創宇信用認證合作優惠
- 周年福利系列:碼云企業版限時10%優惠
- 周年福利系列:想天短說抵現優惠
- think-swoole直播:從零開始掌握swoole開發
- 周年福利系列:B2C開源電商ShopXO授權8折優惠
- 周年福利系列:LayuiAdmin 永久授權限時優惠
- ThinkPHP資源導航站上線——構建生態 服務未來
- ThinkPHP官方技術支持服務和應用服務市場上線公測
- ThinkPHP市場精選——推廣基本要素
- ThinkPHP市場精選——客服聊天專題
- ThinkPHPV6.0.3版本發布——端午安康
- ThinkPHP開發者扶持計劃
- 6.0.3版本關鍵更新及升級事項
- 「ThinkPHP開發者周刊」改版重啟
- ThinkPHP市場精選——企業建站專題
- ThinkPHP 提供統一API接口服務
- ThinkPHP市場精選——直播電商專題
- ThinkAPI服務SDK發布
- 官方服務市場啟用獨立子域名
- ThinkPHP市場精選——刷臉支付專題
- ThinkAPI推出會員服務計劃
- ThinkPHPV6.0.4版本發布——中秋國慶雙節快樂
- ThinkPHPV5.1.40版本發布——常規更新
- 1024程序員節福利走一波
- ThinkPHP V6.0.5版本發布——兼容Composer2.0
- 知識圖譜應用場景——源論技術沙龍
- ThinkPHP5.*版本改進Composer2.0的兼容
- 官方市場雙十一精選推薦
- 技術人做產品有機會么(文末送課程)
- 本周秒殺——古德云售后獲客營銷系統
- ThinkAPI服務更新——支持接口分組和PHP版本依賴調整
- PHP8新特性盤點
- PHP8新特性系列:構造器屬性提升使用及注意事項
- ThinkPHP2021新年寄語
- ThinkPHP V6.0.6&V5.1.41版本發布——兼容PHP8.0
- PHP如何更優雅地調用API接口
- ThinkPHP V6.0.7發布——修正版本
- ThinkAPI服務更新——IP白名單
- 最新版ThinkORM對于時間字段的調整
- ThinkAPI短信接口正式上線
- ThinkPHP V6.0.8版本發布——多環境變量配置支持
- 頂想云寫作服務開啟第一次公測
- ThinkSSL上線——官方SSL/TLS證書服務
- MDBootstrap國內用戶福利——ThinkPHP官方市場首發
- ThinkPHP V6.0.9版本發布——常規更新
- ThinkORM功能盤點——虛擬模型
- 全面支持主流GIT版本庫——云寫作服務第二次公測
- 云寫作服務私有化部署方案之:版本庫私有化
- 看云雙十一活動
- ThinkPHP V6.0.10LTS發布——兼容PHP8.1
- ThinkPHP V6.0.12發布——命令行兼容8.1
- 頂想云知識管理上線公測——構建企業文檔中心和知識庫
- 頂想云上線——助力生態數字化建設
- 618活動進行中——官方市場迎來一波更新
- 頂想云知識管理正式上線——看云文檔啟動遷移服務
- ThinkPHP V6.0.13發布——常規更新
- 頂想云網站助理服務上線——構建產品支持服務
- ThinkPHP發布6.1.0&6.0.14版本——安全更新
- ThinkPHP新版社區上線試運營
- ThinkAPI上架人臉核身接口——助力網站實名認證
- 辭舊迎新——舊版社區停止注冊及發帖
- ThinkPHP6.1.2版本發布——兼容PHP8.2