PHP 8.4 將支援 HTML 5 的解析
自從 PHP 基金會成立以後,PHP 核心維護團隊招募到了許多優秀的新成員,或許是因為有了充足的人力協助開發,PHP 在近幾年的更新下新增了許多功能,讓 PHP 這個老牌語言始終散發著活力。
最新的 8.4 版本即將在今年底正式發佈,這次更新同樣也帶來了許多新功能,其中最讓我眼前為之一亮的新功能是…
PHP 8.4 正式支援 HTML 5 的解析
你可能會想說 HTML 5 都推出這麼久了,PHP 這個 29 歲的老牌語言怎麼到現在都還沒支援?老實說連我也很驚訝。畢竟 HTML 5 在 2008 年推出後到現在已經過了 16 年,我也很好奇為什麼 PHP 始終只支援 HTML 4 的解析。
現在的 PHP 可以使用 DOMDocument
來解析 HTML 4,但如果你嘗試解析 HTML 5 才有的新標籤。
$dom = new DOMDocument();
$dom->loadHTML('<section></section>');
那麼就會得到下面的警告,PHP 會告訴你它不認識這個標籤。
<warning> WARNING </warning> DOMDocument::loadHTML(): Tag section invalid in Entity
解決辦法也是有的,就是請 PHP 無視這個警告。
$dom = new DOMDocument();
$dom->loadHTML('<section></section>', LIBXML_NOERROR);
但有經驗的工程師都知道,這絕對不是解決問題的好方法,因為 HTML 5 相較於 HTML 4 並不只是多了幾個標籤那麼簡單,標籤底下能放哪些標籤的規則也有更動,這會導致 DOMDocument
無法解析出正確的樹狀結構。
如果你有解析 HTML 5 的需求,基本上都會建議使用其他人開發的套件來處理,而不是使用 DOMDocument
。
為什麼長時間不支援 HTML 5 的解析
PHP 之所以過這麼久都不支援 HTML 5,主要原因是 DOMDocument
背後所使用 libxml2 並不支援 HTML 5 的解析。
libxml2 是一個非常熱門的函式庫,主要用來解析 XML 文件格式,並且可以被許多語言呼叫並使用,例如 C#、Python、Ruby 與 PHP … 等。除了 XML,libxml2 也支援對 HTML 的解析,但只支援到第 4 版。這也是為什麼 PHP 始終沒有支援 HTML 5 解析的原因。
libxml2:我本身就不是設計來處理 HTML 的齁~
其實 libxml2 也正在考慮是否加入對 HTML 5 的支援,但目前提案狀態與薛丁格的貓類似,即可能會支援也可能不會支援,因此 libxml2 官方同樣不建議將 libxml2 用在 HTML 的解析上。
新的 HTML 解析器
PHP 8.4 將採用 Lexbor 作為新的 HTML 解析器。Lexbor 已經被許多知名項目所採用,例如 Python 和 Ruby,因此 PHP 官方認為其可靠程度已經得到驗證,便決定以它做為 PHP 新的 HTML 解析器。
雖然 PHP 8.4 加入了新的 HTML 解析器,但原本的 DOMDocument
並不會被取代掉,你還是可以用它來處理 HTML 4 的解析。至於 HTML 5 的解析將會交給新的類別 HTMLDocument
來處理。如果想搶先玩看看新的 HTMLDocument
,可以到 PHP 官方下載 PHP 8.4 的測試版本,或是使用 PHP 核心成員提供的 Dockerfile,來建立擁有新版解析器的 PHP 容器來試玩。
以下就來簡單的試玩一下 HTMLDocument
。
use DOM\HTMLDocument;
// 你可以將 HTML 5 的內容以字串的方式傳給 HTMLDocument
$dom = HTMLDocument::createFromString('<p id="hello">Hello World!</p>');
// Hello World!
var_dump($dom->getElementById('hello')->nodeValue);
// 因為給的 HTML 結構不完整,所以還是會有警告
// tree error unexpected-token-in-initial-mode in Entity
HTMLDocument
也可以用讀取檔案的方式載入 HTML 5 的內容,首先新增一個 index.html
,並在裡面放入 HTML 5 才有的 <nav>
標籤。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<nav class="menu">
<ul>
<li><a href="https://www.google.com">google</a></li>
<li><a href="https://www.microsoft.com/zh-tw">microsoft</a></li>
</ul>
</nav>
</body>
</html>
然後使用 HTMLDocument::createFromFile
來讀取這個檔案。
use DOM\HTMLDocument;
$dom = HTMLDocument::createFromFile("index.html");
foreach ($dom->getElementsByTagName('a') as $a) {
var_dump($a->getAttribute('href'));
}
// 結果
// string(22) "https://www.google.com"
// string(31) "https://www.microsoft.com/zh-tw"
可以看到新版的 HTML 解析器已經不會有無法辨識 HTML 5 標籤的警告產生。
PHP 8.4 除了新的 HTML 解析器,也加入了很多新的實用功能。身為 PHP Dev,真得很期待年底的更新啊。