我剛學 WordPress 佈景主題開發時,卡最久的不是 PHP,而是明明照著教學把 home.php 改好了,首頁卻一點反應都沒有。後來才知道,那個佈景主題沒有上傳 home.php 這個檔案,WordPress 一路往下找、最後用了 index.php。

這就是模板階層(template hierarchy)的邏輯,每次頁面載入都在背後決定「該用哪個檔把這頁畫出來」,搞懂它那天,我才算真的踏進 WordPress 主題的門。從今天開始進入第二部,我們要把傳統佈景主題和 Block Theme 放在一起比較。
很多人以為 Block Theme 是一套全新的東西需要重新學,但在我自己的學習路上,真正的轉捩點是發現一件事:如果你懂傳統主題的模板階層,Block Theme 對你來說只是換了副檔名而已,以下開始深入說明。
先講清楚一件事:模板階層是 WordPress 核心的一套決策流程,跟你用哪套佈景主題無關。使用者點開一個網址,WordPress 要決定「用哪一個模板檔把這頁畫出來」,靠的就是這套由具體到通用的優先順序。
以「打開一篇文章」為例,傳統主題的找檔順序是這樣:
single-{post-type}-{slug}.php — 特定那一篇single-{post-type}.php — 這個內容類型的所有文章single.php — 所有單篇文章singular.php — 所有單一內容(文章與頁面共用)index.php — 全部的最後防線WordPress 由上往下找,找到第一個存在的檔案就停手。所以開頭那個新手的站沒有 single.php,就一路掉到 index.php,他當然改不動。
這套邏輯每種頁面類型都有一份對照,分類頁是 category-{slug}.php → category.php → archive.php → index.php;頁面是 page-{slug}.php → page.php → singular.php → index.php;找不到的網址則走 404.php。共通點是最後全部通往 index.php。這也是為什麼一個只有 index.php 的主題就能跑,它是整棵樹的根。
現在把同一套邏輯搬到 Block Theme,你會發現需要重新記的東西其實很少。
差別只有三個。第一,檔案從 .php 變成 .html。第二,所有模板集中放在 templates/ 資料夾,不再散落在主題根目錄。第三,檔案內容不是 PHP,而是區塊標記(block markup)。至於「該用哪個檔」的那套優先順序完全一樣。
同一篇文章,Block Theme 的找檔順序是:
templates/single-{post-type}-{slug}.html
templates/single-{post-type}.html
templates/single.html
templates/singular.html
templates/index.html
把上面的清單拿來對照,除了路徑前綴多了 templates/、副檔名換成 .html,一個字都沒動。傳統主題那套邏輯可以直接搬過來用。
而 index.html 在 Block Theme 裡的地位,跟 index.php 在傳統主題裡一模一樣:它是必要檔案,是所有其他模板找不到時的最終回退。少了它,這個佈景主題連啟用都不會被 WordPress 認可。
這是唯一需要重新適應的地方。傳統主題的 single.php 裡是 PHP 迴圈、get_header()、get_footer() 這些函式呼叫。Block Theme 的 single.html 則是這樣:
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
<!-- wp:post-title /-->
<!-- wp:post-content /-->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
看那第一行和最後一行。傳統主題用 get_header() 和 get_footer() 把頁首頁尾拉進來,Block Theme 用 wp:template-part 引入 header 與 footer——概念是同一個,都是把重複的區塊抽出來共用。這些 template part 檔案放在 parts/ 資料夾,並在 theme.json 裡登記:
{
"version": 3,
"templateParts": [
{ "area": "header", "name": "header", "title": "Header" },
{ "area": "footer", "name": "footer", "title": "Footer" }
]
}
中間那段 wp:post-title、wp:post-content 對應的就是傳統主題 The Loop 裡的 the_title()、the_content()。名字換了,做的事沒變:從資料庫把這篇文章的標題和內文取出來、放到頁面上。(補充:theme.json 目前最新為 version 3,對應 WordPress 6.6 以後;上面 templateParts 的寫法在 version 2 與 3 完全相同。)
| 概念 | 傳統佈景主題 | Block Theme |
|---|---|---|
| 模板檔位置 | 主題根目錄 | templates/ 資料夾 |
| 副檔名 | .php |
.html |
| 檔案內容 | PHP + HTML | 區塊標記 |
| 單篇文章模板 | single.php |
templates/single.html |
| 頁面模板 | page.php |
templates/page.html |
| 分類彙整 | category.php |
templates/category.html |
| 最終回退 | index.php |
templates/index.html |
| 引入頁首 | get_header() |
wp:template-part (header) |
| 取出標題 | the_title() |
wp:post-title |
| 誰決定用哪個檔 | 模板階層 | 同一套模板階層 |
整張表右邊那欄,只有前三列是真的「不一樣」,剩下的都只是同一件事換個寫法,這也是我想在第二部一開頭就先講模板階層的原因:它是傳統主題和 Block Theme 之間最穩固的那座橋,你在 PHP 主題累積的那套「WordPress 怎麼決定畫哪一頁」的直覺,一分都不會浪費。
模板階層本身沒變,但「你怎麼改這些模板」在 Block Theme 裡變了——傳統主題你打開 single.php 改 PHP,Block Theme 則多了一條路:直接在後台的網站編輯器(Site Editor)用滑鼠拖拉區塊,改完 WordPress 會把結果存進資料庫,覆蓋掉主題資料夾裡的 .html。
這帶來一個新問題:同一個 single 模板,可能同時存在於「主題檔案」和「資料庫」兩個地方,哪一個說了算?這正是全站編輯(Full Site Editing)改變開發與維運方式的核心,我們留到後面幾天再拆解。
今天先記住一句話就夠了:模板階層是你已經會的東西,Block Theme 沒有推翻它,只是把 .php 換成了 .html。下一篇我們往裡面走一層,看看讓 Block Theme 之所以成立的那個檔案——theme.json。
文章目錄:https://oberonlai.blog/category/2026-ithome/