跳至內容
佈景主題

WordPress 區塊範本沒有套用?先從資料庫查起

清掉網站編輯器存在資料庫裡、蓋過你檔案的那份副本,讓 WordPress 重新使用佈景主題的範本檔,接著再排除檔名與快取問題。

發布於

你的範本檔案幾乎可以確定是被資料庫裡的一份副本蓋掉了。只要你在網站編輯器裡打開某個範本並按下儲存,WordPress 就會寫入一筆 wp_template 文章記錄,從此改用那筆記錄,而不是佈景主題資料夾裡的 .html 檔——所以你之後對檔案做的每一次修改,在前台都是看不見的。清掉那筆記錄就是解法,而且在你去動階層、檔名或快取之前,這是第一件該檢查的事。

先確認資料庫副本存在

前往 外觀 → 編輯器 → 範本。任何由 WordPress 從資料庫提供的範本,都會在清單裡被標示出來——依你的 WordPress 版本不同,標籤可能寫著「已自訂」,或是該範本會出現在「已自訂」的篩選條件底下。那個標籤就是全部的答案。只要它在,你的檔案就沒有被使用。

同一件事也可以從指令列確認,這樣更快,而且在網站編輯器本身出問題時照樣可用:

wp post list --post_type=wp_template --fields=ID,post_name,post_status,post_title
wp post list --post_type=wp_template_part --fields=ID,post_name,post_status,post_title

每一列就是一筆資料庫覆寫。post_name 對應範本代稱,所以名為 single 的那一列,正在遮蔽 templates/single.html

有個細節常讓人踩坑:這些記錄是透過分類法術語綁定到佈景主題,而不是透過路徑。如果你把佈景主題的資料夾改名,那些儲存的範本仍然留在資料庫裡,卻不再對應到目前啟用的佈景主題,於是網站突然退回使用檔案。這看起來像是「我的自訂內容不見了」,而不是「我的檔案被忽略」——同一套機制,相反的症狀。

清掉它

在網站編輯器裡,打開範本的選項選單(旁邊那三個點),選擇 清除自訂內容,某些版本的標籤是 重設。這會刪除資料庫記錄,控制權就回到磁碟上的檔案。

如果選單給的是 刪除,而不是清除自訂內容或重設,代表那個範本存在於資料庫,背後沒有檔案。刪掉它會整個移除該範本,WordPress 會沿著階層往下退回。

從 WP-CLI 操作的話,用上面清單裡查到的 ID:

wp post delete 482 --force

這裡請對自己誠實一點:清除自訂內容會永久捨棄你在網站編輯器裡為該範本做的一切,而且無法復原。如果網站編輯器的版本裡有真正的成果,請先把區塊標記複製出來——在編輯器裡打開該範本,切換到程式碼檢視,把內容貼進你的 .html 檔。這樣一來,檔案就成為唯一的真實來源,也不會有東西遺失。

WordPress 怎麼挑選範本

區塊佈景主題使用的階層邏輯和傳統佈景主題一樣,只是換成放在 templates/.html 檔,而不是佈景主題根目錄的 .php 檔。WordPress 從最明確找到最籠統,用第一個存在的檔案。

檢視的內容依此順序尋找
單篇文章single-post-{slug}.htmlsingle-post.htmlsingle.htmlsingular.htmlindex.html
一個頁面page-{slug}.htmlpage-{id}.htmlpage.htmlsingular.htmlindex.html
分類彙整頁category-{slug}.htmlcategory-{id}.htmlcategory.htmlarchive.htmlindex.html
自訂內容型態single-{post-type}.htmlsingle.htmlsingular.htmlindex.html
404 頁面404.htmlindex.html

有兩件事會完全推翻上面這套規則。第一是前面說的資料庫記錄。第二是直接指派給某篇文章或頁面的範本——打開文章編輯器,看側邊欄的「範本」面板,確認那裡是不是選了特定的範本。明確指派永遠贏過階層,而且除非你主動去看,否則完全看不出來。

以代稱為基礎的範本有一種值得牢記的脆弱性。page-about.html 只有在該頁面的代稱是 about 的時候才會比對成功。把頁面改名成 about-us,範本就會停止套用,沒有警告,也沒有錯誤訊息。

範本與範本組件

範本負責算繪一整個檢視畫面,由階層挑選出來。範本組件是片段——頁首、頁尾、側邊欄——由範本引入使用。組件放在 parts/,範本放在 templates/,在資料庫裡則是分開儲存為 wp_template_part 記錄。

常見的困惑是:你改了頁首,結果變更出現在你根本沒想動的頁面上。那是正確的行為。同一個組件被每一個引用它的範本共用。如果你想讓某一個範本使用不同的頁首,就必須另外做一個組件檔,再讓那個範本去引用它——編輯共用的那一個,永遠不會產生逐範本的差異。

反過來的狀況也會發生。你把一整個頁面版面放進 parts/,卻納悶為什麼階層從來不會用到它。組件根本不在階層的候選名單裡,沒有任何請求會直接導向它們。

檔案命名與位置

在假設有什麼更玄的原因之前,先檢查這些:

  • 資料夾是 templates/,複數,放在佈景主題根目錄。不是 template/,也不是 block-templates/block-templates/ 是 Gutenberg 外掛時期、區塊佈景主題還沒進入核心之前的正確名稱,不少教學到現在還這樣寫——在目前的 WordPress 上它不會生效。
  • 範本組件放在 parts/,不是 template-parts/(那是傳統佈景主題放 PHP 片段的慣例)。
  • 副檔名是 .html。放在 templates/ 裡的 .php 檔會被忽略。
  • 檔名要全小寫,並使用連字號。single-Post.htmlsingle_post.html 都不會比對成功。在 macOS 這種不分大小寫的檔案系統上,這樣寫在本機能動,上到 Linux 伺服器就壞掉——標準的「在我電腦上是好的」災難。
  • templates/index.html 必須存在。少了它,WordPress 不會把這個佈景主題歸類為區塊佈景主題,網站編輯器甚至可能根本不會出現。
  • 如果你是在子佈景主題裡工作,它的範本優先權高於父主題。子主題裡一個沒清乾淨的殘留檔案,會默默打敗你正在編輯的父主題檔案。

想讓自訂範本能在文章編輯器裡被選取,還必須在 theme.jsoncustomTemplates 底下宣告,填入檔案的主檔名、給人看的標題,以及適用的內容型態。少了這筆設定,檔案雖然存在,卻永遠不會出現在「範本」面板裡。

快取——最後才檢查

快取確實是真實存在的問題,但它是可能性最低的原因,而一開始就往這裡找,是很多人賠掉一個下午的方式。

清除你的頁面快取;如果你有跑 Redis 或 Memcached 這類常駐物件快取,也一併清空——範本解析的結果可能被存在那裡。然後在略過瀏覽器快取的狀態下重新載入頁面。

沒有幫助的做法是:清除 OPcache。區塊範本是 .html 檔案,永遠不會被 PHP 編譯,所以 OPcache 跟它們毫無關係。如果你曾經覺得清 OPcache 修好了這個問題,那八成是同一時間還有別的東西一起改變了。

還是卡住?

如果沒有資料庫記錄、檔名正確、文章上也沒有明確指派範本、快取也都清過了,那就去看外掛。任何會過濾範本解析流程的東西——頁面編輯器、會員外掛、多語系外掛、線上課程外掛——都可能在請求的後段替換掉自己的範本。切換到預設的區塊佈景主題,並在停用所有外掛的狀態下測試,然後一個一個重新啟用。

還有一種情況:如果範本確實套用了,但畫面是空的,那是另一個問題——請檢查檔案裡的區塊標記是否有效,因為一個格式錯誤的區塊註解,會讓編輯器默默把內容剝掉,而不是拋出錯誤。

FAQ

常見問題

為什麼我的 WordPress 區塊範本沒有套用?

通常是因為資料庫裡有一份儲存的副本蓋過了檔案。只要你在網站編輯器裡編輯範本並按下儲存,WordPress 就會建立一筆 wp_template 文章記錄,並改用它,而不是佈景主題資料夾裡的 .html 檔。從那一刻起,你對檔案做的每一次修改在前台都是看不見的。

要怎麼讓 WordPress 使用我的佈景主題檔案,而不是網站編輯器的版本?

進入「外觀 → 編輯器 → 範本」,找到該範本,用它的選項選單選擇清除自訂內容或重設。這會刪掉資料庫記錄,把控制權交還給磁碟上的檔案。如果選單顯示的是「刪除」而不是「重設」,代表這個範本只存在於資料庫,背後沒有對應的檔案。

WordPress 佈景主題的區塊範本檔要放在哪裡?

完整範本放在佈景主題根目錄的 templates 資料夾,可重複使用的區段放在 parts 資料夾。兩者都使用 .html 副檔名、全小寫檔名,並以連字號而非底線分隔。此外,區塊佈景主題必須有 templates/index.html,否則 WordPress 根本不會把它當成區塊佈景主題。

範本和範本組件差在哪?

範本負責算繪一整個頁面,由範本階層依照目前檢視的內容挑選出來。範本組件則是像頁首或頁尾這樣的片段,由範本引入使用。編輯頁首組件會影響到每一個引用它的範本,這也是為什麼組件的修改常常看起來像是套用到了不該套用的地方。

快取會導致區塊範本無法更新嗎?

有時候會,但它是可能性最低的原因,應該留到最後才檢查。頁面快取和常駐物件快取都可能留著過期的 HTML,所以在下結論前請兩者都清一次。清除 OPcache 在這裡完全沒用,因為區塊範本是 .html 檔案,本來就不會被 PHP 編譯。

為什麼我依頁面代稱建立的範本突然失效了?

以代稱為基礎的範本,是在請求當下拿目前文章的代稱去比對的。改了頁面名稱就會改到代稱,所以當頁面代稱從 about 變成 about-us,page-about.html 就會默默停止比對成功。分類和標籤範本也是同樣道理。解法是把檔名改成新的代稱,或直接在文章編輯器側邊欄明確指定範本。