文章目錄[隱藏] 稍有接觸過(guò) WordPress 主題或插件制作修改的朋友,對(duì) WordPress 的Hook機(jī)制應(yīng)該不陌生,,但通常剛接觸WordPress Hook 的新手,,對(duì)其運(yùn)作原理可能會(huì)有點(diǎn)混亂或模糊。本文針對(duì) WordPress Hook 運(yùn)作大致做個(gè)簡(jiǎn)單的說(shuō)明,,而預(yù)設(shè)讀者是理解基本的 PHP function 語(yǔ)法及運(yùn)作,,但對(duì) WordPress Hook 機(jī)制不是很明白。 Hook機(jī)制里登場(chǎng)的角色先從“登場(chǎng)角色”的個(gè)別說(shuō)明開始: WordPress核心指的是 WordPress 內(nèi)建的程式碼架構(gòu),,提供 WordPress 主要的基本功能,。 Hook也許你早已聽說(shuō),Hook 本身雖是鉤子的意思,,但直譯又有點(diǎn)奇怪,,所以一般通常都不直譯它,而是直接稱它 Hook ,。WordPress 的 Hook 也可以想像成“鉤子”,,這些“鉤子”會(huì)埋在 WordPress 網(wǎng)站中特定幾處的程式碼中,埋進(jìn)去時(shí)使用的語(yǔ)法,,其“標(biāo)示位置”的意義比較大,,沒(méi)有實(shí)質(zhì)運(yùn)作的內(nèi)容。當(dāng)程式執(zhí)行到有埋 Hook 的地方時(shí),,它會(huì)找出所有對(duì)應(yīng)到自己的 Hook Function (也就是所有“鉤到”該 Hook 的 hook function),,并一一執(zhí)行。 因此若沒(méi)有針對(duì)此 Hook 去“加入”要鉤上去的 Hook Function,,執(zhí)行到此什么也不會(huì)做,。因此,它等于是WordPress核心預(yù)留一個(gè)執(zhí)行的機(jī)會(huì)給未來(lái)想要加入定制功能的開發(fā)者,。 Hook FunctionHook Function 里會(huì)有實(shí)質(zhì)運(yùn)作的內(nèi)容,,即是實(shí)作了一些定制功能,可能是存取 DB,、增加 HTML code,、執(zhí)行其他函式等等。我們?cè)?Hook Function 里寫好所需的功能后,,就可以利用“加入至對(duì)應(yīng) Hook”的語(yǔ)法,,把 Hook Function自已鉤到該 Hook 上,,使得該 Hook 被執(zhí)行到時(shí),也會(huì)連帶執(zhí)行自己,。 Hook機(jī)制是如何運(yùn)作的,?舉個(gè)例子,我們拿 wp_head 及 wp_footer 這兩個(gè)內(nèi)建的hook來(lái)說(shuō)明,,wp_head 這個(gè) hook 就是用來(lái)埋在負(fù)責(zé)輸出標(biāo)簽的程式碼中,,而 wp_footer 就是用來(lái)埋在輸出頁(yè)尾的程式碼中 (定義于 wp-includes/general-template.php,用 wp_head() 及 wp_footer() 包裝起來(lái)),。這兩個(gè) hook,,主要都是在布景檔案中使用的,常見會(huì)出現(xiàn)在 header.php 及 footer.php 中,。 請(qǐng)看下面的情境示例圖,,我們把 wp_head 及 wp_footer 看成是”鉤子“,而別的 hook functions 就能來(lái)鈎住它: 我們馬上來(lái)寫一個(gè)簡(jiǎn)單的例子,。我們要寫一個(gè) hook function,,就叫它 print_sth(),然後把它鉤上 wp_head 這個(gè)hook,。因?yàn)?wp_head() 的內(nèi)容實(shí)際上就只有 do_action( 'wp_head' ); 這一行內(nèi)容,,而 wp_footer() 的內(nèi)容也只有 do_action('wp_footer');所以我們直接把 do_action 的語(yǔ)法換到圖上去,,比較容易做說(shuō)明,,因此示意圖變成: 如此,只要執(zhí)行到輸出 header.php 時(shí),,就會(huì)執(zhí)行到 wp_head(),,就如同執(zhí)行到 do_action( 'wp_head' ); 此時(shí)WP核心會(huì)去找所有”鉤上”wp_head 這個(gè) hook 的 hook function,於是就找到我們寫的 print_sth() ,,然後就執(zhí)行它,,所以結(jié)果它做的事就會(huì)出現(xiàn)在網(wǎng)站上,也完成了”定制”的動(dòng)作: 簡(jiǎn)單的說(shuō),,Hook 機(jī)制就是:WP 核心或其他插件,、主題 提供想定制功能的人一個(gè)置入定制程式碼(Hook Function)到特定的執(zhí)行時(shí)間點(diǎn)(Hook)的機(jī)會(huì)。 WordPress的Action Hook與Filter HookWordPress中的 Hook 有兩種,,分別是”Action Hook“及”Filter Hook“,,我們剛才舉例的 wp_head 及wp_footer 都是屬於 Action Hook。不過(guò),,一開始你可以先把這兩種 Hook 看成是一樣的東西,,只是 Filter 多了一點(diǎn)點(diǎn)不同的特色,接著說(shuō)明。 Action HookWP核心 (或主題,、插件)在做它們?cè)撟龅氖聲r(shí),,如果執(zhí)行到有埋 action hook 的程式碼 (即是 do_action 語(yǔ)法) 時(shí),會(huì)去找尋對(duì)應(yīng)到的 hook functions,,進(jìn)而執(zhí)行這些 hook functions(即那些透過(guò) add_action() 來(lái)加入的 hook functions),,藉此完成定制功能。WP核心并不期待 Action Hook functions 會(huì)有回傳值,,所以這里的 hook function 只被視為一個(gè)”獨(dú)立切出來(lái)運(yùn)作的功能“。 WP核心做它該做的事,,你做你想做的事,,做完就各自結(jié)束。 Filter Hook跟 Action Hook 一樣,,WP核心 (或主題,、插件)在做它們?cè)撟龅氖聲r(shí),如果執(zhí)行到有埋 filter hook 的程式碼 (即是apply_filters語(yǔ)法) 時(shí),,就會(huì)去找尋對(duì)應(yīng)的 hook functions ,,進(jìn)而執(zhí)行這些 hook functions(即那些透過(guò)add_filter() 來(lái)加入的 hook functions ),藉此完成定制功能,。與 Action Hook 不同之處是,,所有”鈎上“ Filter Hook 的 hook functions 通常都會(huì)接收到參數(shù),而WP核心會(huì)期待你拿到它提供的參數(shù),,并做完你想做的事后,,要回傳(return)一個(gè)值,讓W(xué)P核心再利用你回傳的值來(lái)接著完成它該做的事,。 透過(guò)你的干涉,,修改了WP核心丟給你的參數(shù),WP核心再接著拿你改過(guò)的參數(shù),,繼續(xù)完成它該做的事,,此動(dòng)作就像”過(guò)濾“的動(dòng)作,因而得名 filter,。 比較Action Hook與Filter Hook的操作語(yǔ)法比較一下兩種 Hook 在埋進(jìn)某處程式碼時(shí)所用的語(yǔ)法,,假設(shè)我們?cè)谀程?(可能是在輸出頁(yè)首的程式碼處,或輸出文章標(biāo)題,、文章內(nèi)容,、側(cè)邊欄…等地方,要”出現(xiàn)定制效果“的地方)埋下這兩種 hook:
然后我們可以在某處 (可能是其他插件,、functions.php 等處,要”實(shí)現(xiàn)定制功能“的地方)添加對(duì)應(yīng)的 hook function:
所以其實(shí)兩種 Hook 的運(yùn)作方式幾乎一樣,,只差在增加 Action Hook 函式不需回傳值,,而增加 Filter Hook function時(shí),你必須要回傳一個(gè)值,。所以 Filter Hook 函式通常都有提供參數(shù),,讓想定制的人可以取得它,處理后再回傳,。 但如果有一個(gè) Filter Hook,,它沒(méi)有任何 hook function 有去鉤它,它該怎么取得回傳值,?答案是,,直接拿第一個(gè)它給的參數(shù),以上面的例子來(lái)說(shuō),,它會(huì)直接拿 $a 丟進(jìn) $c ,。另外,其實(shí)我們也可以把 filter 寫的跟 action 一樣,,只要不回傳值就行,,但 action hook 就沒(méi)辦法”模仿“ filter hook,因?yàn)闊o(wú)法取得回傳值,。 Hook Function的優(yōu)先序(Priority)如果有很多地方(主題或者插件的 functions.php)都 添加同一個(gè) hook ,,會(huì)怎么決定出現(xiàn)順序?答案很顯然是可以透過(guò) Hook Function 的 Priority 參數(shù)來(lái)作優(yōu)先序的設(shè)定: 就像我們剛才說(shuō)明的例子中,,我們使用 add_filter 加入 special_func 時(shí)設(shè)定的優(yōu)先序是 10 ,,這也是 Priority 參數(shù)的預(yù)設(shè)值。如果你希望它能優(yōu)先被執(zhí)行,,就設(shè)定小于 10 的數(shù)字,,反之,就設(shè)個(gè) 100,、500 之類的,,讓它延后被執(zhí)行,。 但其實(shí)這里有個(gè)隱含的沖突問(wèn)題。 以 wp_head 這個(gè) hook 為例,,如果我寫了一個(gè)插件,,希望透過(guò) wp_head 來(lái)輸出”增加 a.css 檔案“的 HTML 語(yǔ)法,而 a.css 會(huì)重新設(shè)定 body 元素的樣式,,所以我希望它可以最后才被匯入,,不要被其他 css 檔干擾,于是我將 Priority 設(shè)為 900,,但我怎么知道 Priority 900 夠不夠大,?若某個(gè)WP網(wǎng)站,它除了安裝我的插件,,也安裝了其他插件,,而其他插件剛好也重新設(shè)定body元素的樣式,然后把 Priority 設(shè)為 950,,此時(shí)我寫的插件在處理 body 樣式時(shí)就出事了,于是就跟其他插件沖突了,。 所以此時(shí)我們需要了解的是:我的WP網(wǎng)站可能裝了很多插件,,我怎么知道同一個(gè) Hook 被加了多少 Hook Function,而每個(gè) Hook Function 的 Priority 被設(shè)定為多少,? 答案是,,我們可以透過(guò) $wp_filters 這個(gè) global 變數(shù)來(lái)取得所有 hook 的信息,像是如下的 function:
當(dāng)我們呼叫 list_hooked_functions('wp_head'); 時(shí),,就會(huì)列出 wp_head 這個(gè) Hook 所鉤住的所有 hook function,,可以看到 priority 10 之后有好幾個(gè)都沒(méi)有數(shù)字,因?yàn)樗鼈兌紱](méi)有特別指定 priority,,所以都是 10 ,,包括我們剛才寫的 print_sth 也在其中:
所以,沖突很難提早避免,,但發(fā)生沖突時(shí),,可以預(yù)先思考有沒(méi)有可能是因?yàn)?priority 的設(shè)定,導(dǎo)致結(jié)果跟預(yù)期不符合,。 |
|
來(lái)自: 最后一年 > 《wordpress》