我們在 WordPress 發表文章的時候,有時會遇到一些特殊的需求,比如把文章中的鏈接變成可點擊,或者過濾掉文章內容 HTML 標籤中的某種屬性等。
我近期的項目中就遇到了後面的這個需求,因為直接粘貼複製網絡上的文章,往往會夾帶着 HTML 的 class 、 id 和 style 屬性值,這些無用的內容會潛在的影響正文的排版佈局和樣式,所以要過濾掉。
解決思路
如果想要過濾掉髮布文章時,文章內容中 HTML 標籤中的 class 、 id 和 style 等屬性,首先需要在摁下 「發表」 按鈕的時候,使用 PHP 正則匹配對要發表的文章內容進行正則匹配處理,替換掉無用的內容,最後繼續執行插入數據庫的操作。所以這個問題就分成了幾個小步驟:
- 「獲取」 文章內容,傳遞給處理函數
- 處理函數使用正則匹配對文章內容進行處理
- 將處理好的內容返回,讓 WordPress 把內容插入數據庫
解決方案
面對第一個步驟,WordPress 有一個很強大的 「鈎子」(hook) 開發機制,實現各種功能和開發插件必不可少的功能。簡單的説,就是 WordPress 在執行某些關鍵性的操作時 (例如發表文章、發表評論、修改文章、刪除文章、新增用户等等),會插入一個 「鈎子」,這樣你就可以在 functions.php 中或者插件中,使用 add_action 或者 add_filter 函數掛上這個 「鈎子」,並增加自定義的函數對數據進行一個動作或者進行過濾。
例如在發表文章的時候,在提交到插入數據庫之前,會有一個叫做 wp_insert_post_data 「鈎子」,如果你想對文章進行過濾處理,你就需要在 functions.php 文件中,新建一個處理函數,然後將對應處理函數綁定到這個鈎子上面。
首先,你需要找到你要用的 「鈎子」,你需要瀏覽 WordPress 官方的 Filter Reference 和 Action Reference 文檔,裏面是長長的 「鈎子」 列表,看一下下面的説明,然後找到對應的 「鈎子」 就可以開始使用了。比較常用的 「鈎子」 已經給出官方文檔和使用説明瞭,例如:wp_insert_post_data,不過由於列表太長了,大部分的沒有給出很詳細的使用説明,就需要你按照經驗來使用。
找到需要的 「鈎子」 之後,使用 add_filter 函數 (具體用法可以看一下官方文檔:add filter) 將鈎子和處理函數進行掛鈎函數用法如下:
add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1);
就本例而言,基本結構如下:
<?php
function wpjam_insert_post_data( $data , $postarr ) {
// 處理函數的邏輯部分和功能代碼
return $data;
}
add_filter( 'wp_insert_post_data', 'wpjam_insert_post_data', '99', 2 );
?>
這樣,我們的第一個步驟就完成了。下面來編寫函數的處理代碼。既然要過濾文章中的具有某些特徵的代碼,所以需要使用 PHP 的正則匹配替換掉。可以使用如下的 PHP 代碼:
$date = preg_replace('/<([a-z]+?)s+?.*?>/i', '<$1>', $date);
根據 wp_insert_post_data 文檔可以看出,傳遞進去的 $data 數組裏面是文章的相關信息,我們需要處理的是正文內容,所以使用 $date[『post_content』] 和 $date[『post_content_filtered』] 這兩個變量,那麼就可以寫出下面這段代碼:
function wpjam_insert_post_data( $data , $postarr ) {
$date['post_content_filtered'] = preg_replace('/<([a-z]+?)s+?.*?>/i', '<$1>', $date['post_content_filtered']);
$date['post_content'] = preg_replace('/<([a-z]+?)s+?.*?>/i', '<$1>', $date['post_content']);
return $data;
}
add_filter( 'wp_insert_post_data', 'wpjam_insert_post_data', '99', 2 );
因為函數裏面已經將處理後的數據 return 了,這樣第二步和第三步就完成了,我們的這個需求也就實現了。
總結
正是因為有了這種開發機制,WordPress 的靈活性和擴展性大大增強。如果你還想對文章進行其他處理 (例如文章末尾加版權信息等),都可以繼續編寫函數,掛鈎在對應的鈎子即可。