iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
1
自我挑戰組

WordPress 客製化從 0 開始系列 第 21

Day 21 客製化 WordPress 程式的起點:勾點 (hook)

  • 分享至 

  • xImage
  •  

大家好,我是 Eric。

昨天介紹了 PHP 變數與函式的基本定義方式,接下來我們要介紹 WordPress 中扮演要角的函式們:勾點 (Hook)。所謂的勾點,就是在整個網頁在計算過程中,在特定階段執行特定行為的函式。

勾點分為兩種:篩選器 (filter) 與動作 (action)。

動作 (do_action)

動作勾點的基本語法如下:

do_action( '動作勾點名稱' );
add_action( '動作勾點名稱', '函式名稱', '優先度 (整數,選填)', '接受參數 (整數,選填)' );

根據 WordPress Codex 的定義,動作指的是

在 WordPress 事件發生時,同時觸發特定函式 (functions)。

或者說:

「WordPress 正在 OOO,這時候我也 XXX。」

簡單來說,我們可以透過 add_action 的方式,將函式的程式碼片段插入 do_action 的位置。舉例來說,我們在自訂的 Twenty Twenty 子佈景主題中加入 header.php 檔案,用以取代上層佈景主題,接著在第 27 行加入一段 do_action

	<body <?php body_class(); ?>>

		<?php
        do_action( 'before_wp_body_open' );
		wp_body_open();
		?>

接著,我們在子佈景主題的 functions.php 中加入下列程式碼片段:

add_action( 'before_wp_body_open', 'do_me_before' );
function do_me_before(){
    echo '<p>我會比 wp_body_open 還要早出現。</p>';
}

add_action( 'wp_body_open', 'the_open_part' );
function the_open_part(){
    echo '<p>這是 wp_body_open 出現的時機。</p>';
}

在上述的例子中,會看到 do_me_before 的段落元素出現在 the_open_part 之前。而在這兩個段落出現後,才會看到網頁剩下的內容 (頁首、導覽列等)。

如果有多個函式指向同一個勾點,那麼就會有優先順序的問題,此時就要透過 add_action( '勾點名稱', '函式名稱', 10 ); 的方式指定順序。預設值是 10,數字越大越後面才執行,因此如果有外掛發生衝突的時候,不妨檢查看看是不是有多個外掛同時使用到同一個動作勾點。

wp_enqueue_scripts

還記得我們在前面曾經看過 add_action( 'wp_enqueue_scripts', 'function_name' ); 嗎?這個勾點便是在告訴 WordPress 在載入 JavaScript 程式碼與 CSS 樣式表的時候,將 wp_enqueue_scriptwp_enqueue_style 中的樣式一併載入。

關於 WordPress 核心程式的動作順序,可以參考這篇文章

篩選器

篩選器的基本語法是:

apply_filters( '篩選器勾點名稱' );
add_filter( '篩選器勾點名稱', '函式名稱', '優先度 (整數,選填)', '接受參數 (整數,選填)' );

根據 WordPress Codex 的定義,篩選器指的是

在 WordPress 將資料於資料庫與瀏覽器間傳遞的過程中,篩選特定資料並回傳已經過轉換的值。

或者說:

現在 WordPress 正要輸出/入 OOO,但我想先 XXX。

do_action 類似,我們可以透過 apply_filters 的方法,在自己所希望的位置添加篩選器。

我們可以參考 template-parts/content.php 程式碼中的第 32 行:

/* Line 32 */
if ( is_search() || ! is_singular() && 'summary' === get_theme_mod( 'blog_content', 'full' ) ) {
    the_excerpt();
} else {
    the_content( __( 'Continue reading', 'twentytwenty' ) );
}

我們接著查詢 the_content 這個函式,看到這個函式的主要內容是 apply_filters( 'the_content' ); 的內容:

function the_content( $more_link_text = null, $strip_teaser = false ) {
    $content = get_the_content( $more_link_text, $strip_teaser );
 
    /**
     * Filters the post content.
     *
     * @since 0.71
     *
     * @param string $content Content of the current post.
     */
    $content = apply_filters( 'the_content', $content );
    $content = str_replace( ']]>', ']]&gt;', $content );
    echo $content;
}

因此我們如果用 add_filter 的篩選器勾點,先將文章內容 $content 進行處理,那麼這段被處理過的內容,會再作後再透過 str_replace 這個函式,將 ]]> 取代為 ]]&gt

在 AMP 版本載入網站字型

如果你安裝了 WordPress 官方開發的 AMP 外掛,當你啟用閱讀器模式時,並不會安裝網路字型。因此,我們可以透過 AMP 提供的勾點,加入自訂的網路字型:

add_filter( 'amp_post_template_data', function( $data ){ 
	$data['font_urls'] = array(
		'custom' => 'https://fonts.googleapis.com/css2?family=Noto+Sans+TC&family=Ubuntu&display=swap',
	);
	return $data;
});
add_action( 'amp_post_template_css', function(){ ?>
	body
	{
		font-family: "Ubuntu", "Noto Sans TC", sans-serif;
	}
<?php });

有關 WordPress 的 AMP 外掛說明,可以參考其官方網站,在這個頁面中可以查詢到更多不同的延伸應用。

移除靜態資源的版本資訊

在大多數的網站安全性文章中,都會提到「靜態資源的版本資訊是安全漏洞」。這是因為有些漏洞公諸於世後,一旦有心人士注意到你的網站使用的是舊版檔案,便可能使用該漏洞攻擊你的網站。因此移除靜態資源的版本資訊,算是網站安全的基本設定之一。

function remove_version_query( $src ) {
    if ( strpos( $src, 'ver=' ) ) {
        $src = remove_query_arg( 'ver', $src );
    }
    return $src;
}
add_filter( 'style_loader_src', 'remove_version_query', 999 );
add_filter( 'script_loader_src', 'remove_version_query', 999 );

這個程式碼片段會在樣式表的 <link> 元素與 <script> 元素輸出至頁面前,查詢靜態檔案來源網址中是否有 ver 這個參數,如果有,便將該參數移除。

常見勾點

名稱 | 類型 | 說明
------+------+------
wp_enqueue_scripts | action | WordPress 開始引入 CSS、JS 檔案時的動作。
wp_head | action | 所有會在 wp_head() 執行時的動作,包含載入頁面中繼資料 (meta)、引入 CSS、JS 檔案等。
the_post | action | 在 WordPress 完成文章查詢請求後的動作。
wp_footer | action | 所有會在 wp_footer() 執行時的動作,譬如載入客製化的 JavaScript 等。
body_class | filter | 在導出 body 元素的 CSS 類型時進行篩選、改寫。
get_the_excerpt | filter | 在取得文章內容摘要時,進行篩選、改寫。可用於自訂文章內容摘要長度的時候。
manage_posts_columns | filter | 在各文章類型 (post type) 的管理頁面中,顯示特定欄位時使用。
the_content | filter | 篩選文章內容,可以搭配 preg_replace 等方式,取代文章中的特定字元。

結語

在進入 PHP 篇章後,我們會開始更廣泛的使用勾點的方式來進行客製化。

不只是 WordPress 的核心程式,許多外掛也會透過勾點的方式來提高客製化的彈性。以 Contact Form 7 為例,它也提供了許多勾點,在產生表單的 HTML 代碼前,可以先將表單處理過。

在透過 WordPress 的勾點機制進行客製化前,你可以像前面探討 apply_filters 的方式,透過追蹤函式的定義,找到最根本的勾點,並透過 add_actionadd_filter 來客製化不同的功能。

明天我們會介紹 WordPress 客製化的另一個重要元素:自訂內容類型 (Custom Post Type)。

延伸閱讀

勾點 (Hook) 初探
WordPress的Hook機制與原理
【第 04 天】聊聊 WordPress 的 Action Hooks
【第 05 天】聊聊 WordPress 的 Filter Hooks


上一篇
Day 20 WordPress 客製化從 1 開始:子佈景主題與 PHP
下一篇
Day 22 客製化 WordPress 的精髓:內容類型 (post type)
系列文
WordPress 客製化從 0 開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言