多數人以為,只要是 WordPress 的客製化程式碼,全都往 functions.php 一貼就對了。它像一個萬用抽屜,追蹤碼、自訂欄位、API 串接、調摘要字數,什麼都能塞。實際上,這個檔案是有脾氣的。它只在你現在這個主題被啟用時才會被讀取,一旦換了主題或子主題失效,裡面的程式碼會整批跟著消失。
問題就在這裡。有些客製化跟著主題走沒關係(本來就是為這個版面做的),但有些是網站的核心功能,像是串接金流的 API、自訂的文章類型,這種東西如果因為換個佈景就不見了,網站多半會出狀況。functions.php 子主題設定的重點,從來不是「怎麼把程式碼寫進去」,而是「這段程式碼到底該不該放進去」。 同樣一段客製化,可以放子主題的 functions.php、包成一個獨立外掛,或交給程式碼片段管理外掛,這三個地方分工不同、風險等級也不同。
先從 functions.php 原本是拿來做什麼的講起,再一路拆到你手上這段程式碼該落在哪裡。
所有客製化都該塞進 functions.php 嗎?
functions.php 這個檔案原本的設計定位,是「主題專屬」的功能擴充點。WordPress 官方的主題開發文件講得很直白,這個檔案的行為就像一個外掛,會替網站加上額外的功能,但它只適用於那個主題,一旦主題被換掉,這些功能就再也用不了。換句話說,它天生就是綁在某個佈景上的,不是網站層級的公共空間。
那為什麼「什麼都塞進 functions.php」的習慣會這麼普遍?很大一部分是複製貼上文化養出來的。網路上大量教學、論壇解答,遇到「怎麼做到某某效果」的問題,最省事的回答就是「把這段貼進你的 functions.php」;現在再加上請 ChatGPT、Claude 生成一段程式碼,它們給你的答案也幾乎都預設你會貼進 functions.php。久而久之,這個檔案就被當成了所有客製化的收納箱。
但「貼進 functions.php」這個建議,只有對一種客製化才真正成立,那就是跟畫面顯示、跟這個主題外觀直接相關的調整。WordPress 的整體設計哲學是「主題管外觀、外掛管功能」。這是分工,不是誰高誰低。摘要要顯示幾個字、選單註冊在哪個位置、這個版型專屬的小工具,這些理所當然跟著主題走。可是一旦你要處理的是「網站功能」性質的東西,例如追蹤碼、自訂欄位、對外 API,把它綁進主題的 functions.php,就等於在替一顆隨時可能被拔掉的地基埋雷。
子主題 functions.php、獨立外掛、Code Snippets 外掛,有什麼差異?
把這三個選項並排來看,會比一直糾結「哪個比較好」清楚得多。它們的差別可以濃縮成四個問題:這段程式碼什麼時候被載入、它跟不跟主題綁在一起、換主題或更新之後會不會消失、除錯時能不能單獨把它關掉。
先講載入時機這條隱形的規則。WordPress 讀取程式碼是有先後順序的:最早載入的是一種叫 mu-plugins(must-use plugins,必用外掛)的東西,接著是一般外掛,最後才輪到主題的 functions.php。官方文件特別提到,mu-plugins 會在一般外掛之前被 PHP 載入,所以它掛上的 hook 會影響到後面所有外掛。這個順序之所以重要,是因為它決定了「誰能覆寫誰」。放得越早的程式碼,越有機會被後面的東西接手或蓋過。
理解了這層之後,三個放置點各自適合什麼,就不是憑感覺,而是有邏輯可循的。以下分開來看。
子主題 functions.php:跟著這個主題外觀走的客製化
子主題的 functions.php 只該放一種東西,就是跟這個主題的顯示邏輯直接相關的客製化。調整文章摘要要截多少字、註冊一個新的選單位置、加進這個版型專屬的側邊小工具。這些放這裡剛剛好,因為它們本來就是為了這個外觀而存在的。
這裡有個常被誤會成「缺陷」的特性,這些客製化會跟著主題一起存亡,你哪天換了佈景,它們理所當然就不見了。但這其實是設計上如此,而不是壞掉。你會換掉的是整個外觀,那些專門為舊外觀寫的顯示調整,本來就不該硬留到新外觀上。子主題還多了一層保護,它的 functions.php 會在父主題的 functions.php 之前被載入,用來擴充或覆寫父主題的功能,而不是把父主題那個檔案整個取代掉。兩個檔案是並存、依序執行的。
獨立外掛:不管換不換主題都要留著的功能
功能性的客製化,該放進一個獨立外掛裡。自訂文章類型、進階的自訂欄位、對外的 API 串接、跟 WooCommerce 有關的商業邏輯。這些都屬於「網站的功能」,跟你當下用哪個佈景一點關係都沒有。
判斷的關鍵句只有一句,如果這段程式碼因為換主題就消失,網站會不會因此出問題?會,那它就不該綁在主題上。一個賣東西的網站,商品類型、結帳邏輯不能因為改版面就跟著蒸發;追蹤與轉換的程式碼也一樣。把這類東西包成獨立外掛,它就用一種不依賴任何主題的方式存在,你之後怎麼換佈景、換幾次,它都穩穩待在那裡。
Code Snippets 外掛:不想自己養一個外掛結構時的中間選項
不是每個人都想為了幾段程式碼,去建一整個外掛的資料夾結構、寫外掛的檔頭註解、處理啟用停用的細節。程式碼片段管理外掛(例如 Code Snippets)就是為這種情境準備的中間選項,它落在「自己寫外掛」和「塞進 functions.php」中間。
它的做法是把每一段程式碼存進 WordPress 資料庫(存在一張叫 wp_snippets 的資料表裡),而不是寫在某個檔案。官方說明也講得很清楚,這些片段獨立於主題,也不受 WordPress 升級影響。管理起來就像啟用、停用外掛一樣,一段一段可以單獨開關。這對除錯特別有用,懷疑哪段出問題,關掉那一段就好,不用去翻整個檔案。它還多了兩道安全網:存檔之前會先檢查語法,抓到會讓網站掛掉的錯誤就擋下來、不讓它上線;萬一真的出事,還有一個安全模式,只要在網址後面加上安全模式參數 ?snippets-safe-mode=1,就會暫時停掉所有片段,讓你把後台救回來、去關掉那段有問題的程式碼。對於想要客製化能撐過主題更新、又不想自己維護外掛結構的人,這是很務實的一條路。

三選一:怎麼判斷這段程式碼該放哪?
把上面那套分類,收成一個你可以當場套用的判斷邏輯。主判準只有一句話:這段程式碼,換了主題之後還需不需要?
答案是「不需要,它就是為這個外觀寫的」,放子主題的 functions.php。答案是「需要,這是網站的功能」,包成獨立外掛,或交給程式碼片段管理外掛。這個問句之所以好用,是因為它把「這是外觀還是功能」這個抽象分類,翻譯成了一個你當下就能回答的具體情境。想像自己下週換了佈景,這段東西還想不想留著。
這裡順帶解掉一個很常見的疑問,也就是子主題的 functions.php 會不會被主題更新蓋掉?子主題本身的檔案不會被父主題的更新覆蓋,這正是我們用子主題的原因。父主題再怎麼更新,你的子主題檔案都安然無事。真正會出事的情況,是有人沒建子主題,直接把程式碼改進了父主題原本的 functions.php,那父主題一更新,整個檔案被新版覆蓋,客製化就一次清空。所以問題從來不是子主題會不會被蓋,而是有沒有改錯地方。
還有兩點值得先講清楚。第一,子主題 functions.php 跟 Code Snippets 並不互斥,你完全可以一邊用子主題放外觀相關的調整、一邊用片段外掛管功能性的程式碼,兩者同時存在沒有衝突。第二,如果這個網站是團隊多人維護、或者未來要交接給下一個維運的人,程式碼片段管理外掛通常比較好追蹤:每一段獨立、有名稱、能單獨開關、還能匯出匯入,接手的人在後台就能一眼看清有哪些客製化,不必去翻一個動輒幾百行、註解又不齊的 functions.php。至於程式碼量很小、又只給這個網站自己用的零星調整,直接放 functions.php 反而輕便;量大、或想在多個專案間重複使用,模組化成外掛才划算。
直接改主題原本的 functions.php,風險有多大?
風險比多數人想的大,而且它是一條會連環出事的鏈。改主題原始的 functions.php,最典型的災情起點是一個小小的 PHP 語法錯誤:少了一個分號、括號沒對齊、複製時漏了一段。這種錯誤在 PHP 眼裡是致命的,它會直接讓網站前台變成一片空白,這就是俗稱的白屏死機。
真正棘手的是接下來。如果你是透過 WordPress 後台的「主題編輯器」直接改的,那個空白很可能連後台一起吞掉,因為後台某些頁面也要載入這個壞掉的 functions.php,於是你連進去把程式碼改回來的門都被鎖上了。這條鏈的關鍵起點,就是後台主題編輯器在你按下存檔之前,完全沒有事前的語法檢查:它不會攔你,錯的程式碼照樣存進去、照樣執行、照樣讓網站掛掉。這一點正好跟 Code Snippets 那類外掛「存檔前先驗語法、有問題先擋下來」的機制形成強烈對比。一個是零防護,一個是有守門員。

萬一真的白屏了,正確的排除順序是冷靜地繞過後台去修檔案,而不是慌亂亂刪。用 FTP 或 SFTP 連進主機、或透過主機控制台的檔案管理員,找到那個 functions.php,把它改回上一版正確的備份;如果一時找不到備份,退一步的做法是暫時停用出問題的主題(例如把主題資料夾改個名字,WordPress 找不到會自動退回預設主題),先讓網站活過來,再回頭處理程式碼。整個過程的核心心法很簡單,問題出在某個檔案,就從檔案系統去解,別在已經進不去的後台裡繼續掙扎。
想客製化又怕改壞網站,正確的操作順序是什麼?
怕改壞,其實有一套穩的流程可以走。把前面所有判準串起來,實際動手時大致是這幾步。
第一步,先分類,不要先動手。拿到一段程式碼,先用那句判準問自己:換主題還需不需要它?屬於主題外觀類,往子主題走;屬於功能類、或你根本不確定將來會不會換主題,往程式碼片段外掛或獨立外掛走。分類這一步花不了幾秒,卻決定了後面所有事。
第二步,如果是外觀類、而你手上還沒有子主題,就先把子主題建起來。原則性的動作很單純:在主題目錄下新增一個子主題資料夾,裡面放一個 style.css(在檔頭註明它的父主題是誰)和一個 functions.php,把外觀相關的客製化寫進這個 functions.php。子主題的 functions.php 會在父主題之前載入,屬於官方認可、風險較低的擴充父主題方式,而不是去動父主題原始檔。這裡只講建立子主題的原則,完整的子主題製作細節是另一個主題,不在這篇展開。
第三步,如果是功能類、或你不想維護一整個外掛結構,就改用程式碼片段管理外掛。它存檔前會先檢查語法,等於在「先在測試站試跑」之外,多給你一道自動的防線。
第四步,也是最容易被跳過的一步:上線之前,一律先在測試站或本機環境試跑,不要直接在正式站的後台編輯器裡貼上就存檔。正式站是給訪客看的,任何沒驗證過的程式碼都不該第一次就在那裡執行。
最後,改動之後別急著關頁面,實際去看看網站前台顯示正不正常、後台各個功能點得進去,確認一切沒事,這次客製化才算真的收尾。
用 AI 生成的程式碼,該貼去哪裡?
現在很多客製化程式碼,是直接請 ChatGPT 或 Claude 做出來的,描述一下需求,它就吐一段 functions.php 用的 PHP 給你。方便歸方便,但這裡有兩個 AI 通常不會主動提醒你的盲點。
第一,AI 給你程式碼的時候,幾乎不會告訴你「這段該放子主題還是該放外掛」。它預設你會貼進 functions.php,因為那是網路上最常見的寫法,但這篇一路講下來的判準,對 AI 生成的程式碼一樣適用:先看它是改外觀還是加功能,再決定落點,別因為是 AI 給的就自動塞進 functions.php。
第二,AI 不會知道你的網站上已經裝了哪些外掛、用了哪個主題,所以它不會提醒你,它給的函式名稱有沒有可能跟現有的東西撞名。兩段程式碼用了同一個函式名,PHP 會直接報致命錯誤、網站掛掉。務實的做法是在貼上之前,替 AI 給的函式加一個你自己的自訂前綴(例如把 add_custom_field 改成 pongo_add_custom_field 這類獨一無二的名字),把撞名的機率壓到最低。
順序其實跟前面完全一樣:AI 產生程式碼之後,先照類型分好該放哪,接著在有語法檢查機制的地方、或測試站先過一關,確認語法沒錯、也不跟現有程式碼衝突,最後才透過有防護的方式上線,而不是複製、貼上正式站後台編輯器、按存檔一條龍。AI 幫你寫程式碼,省的是打字的力氣,不是把關的責任。
判斷一段程式碼該放哪裡,回到最前面那句判準:換了主題,它還需不需要?需要就讓它獨立於主題存在(獨立外掛或程式碼片段外掛),不需要就安心放進子主題的 functions.php。直接動主題原始的 functions.php 不是不能碰,而是在碰之前,要先確定自己走的是風險最低、隨時能退回來的那條路。往後就算程式碼是 AI 幫忙寫的,這套判斷邏輯照樣管用。工具會一直換,但「這東西到底屬於外觀還是功能」這個問題,永遠是你該先回答的第一題。
