大家好,我是 Eric。
昨天我們介紹完 WordPress 的自訂內容類型,今天我們要再進一步介紹客製化的另一個環節:自訂欄位。我們在昨天的內容曾提到使用自訂欄位的情境:
附屬於個別內容的中繼資料 (meta data),譬如說各分店的地址與聯絡方式。
以我們常見的 SEO 外掛來說,當你安裝 SEO 外掛後,你在編輯文章時,便會出現其他欄位,可以讓你填寫不同的中繼資料,如頁面的標題、敘述,甚至是社群網路的中繼資料 (如 Open Graph 標記)。
和自訂內容類型一樣,自訂欄位也能透過外掛來管理。其中,使用最為廣泛的,便是 Advanced Custom Fields (俗稱「ACF」) 這款外掛。透過 ACF,我們可以藉由介面直接管理自訂欄位。
在免費版的 ACF 中,有 32 種欄位可供選擇使用,這裡簡介幾種常見的欄位:
欄位名稱 | 說明
-------+-------
文字 (Text) | 用來儲存單行文字,譬如 SEO 外掛中的「標題」。
文字區域 (Text area) | 用來儲存多行文字,譬如 SEO 外掛中的「敘述」。
圖片 (Image) | 可以用來上傳圖片,並回傳圖片物件或陣列。
日期選擇器 (Date Picker) | 可以用來儲存特定日期,可用於自訂文章有效期限 (例如促銷)。
文章物件 (Post Object) | 可以用來關聯一系列的內容 (post)。
關於「文章物件」,可以特別提出來說一下。在昨天的文章中,我們曾提到 WordPress 將所有內容都當成文章的做法,讓文章之間的關聯變得較困難。其中一種方法,就是透過文章物件來建立內容間的關聯。實際的作法,我們會在之後的實務操作中再說明。
取得 ACF 資料的基本程式碼如下:
get_field( '欄位名稱', 內容 ID, 是否格式化 );
// 內容 ID 是選填欄位,預設是當前文章;格式化是選填欄位,預設值是 true。
the_field( '欄位名稱', 內容 ID, 是否格式化 );
有時候網站會需要發布「贊助商」貼文,這時候我們便可以透過自訂欄位的方式,替這些文章加上「贊助」的標記。
首先,我們在 ACF 中自訂一個欄位群組,並新增一個 True/False 欄位,姑且命名為 PR,欄位名稱 pr
。
接著,我們在子佈景主題的 functions.php 中,加入下列的程式碼:
add_filter( 'post_class', 'eric_is_pr', 10, 3 ); // 利用 post_class 篩選器,加入 is-pr 這個類型
function eric_is_pr( $classes, $class, $post_id ){
if ( ! function_exists( 'get_field' ) ) {
return $classes;
} else {
$class_list = [];
$class_list[] = get_field( 'pr', $post_id ) ? 'is-pr' : null ;
return array_merge( $classes, $class_list );
}
}
接著我們再替擁有 is-pr
這個樣式類型的元素加上樣式。
.is-pr entry-title::after {
content: '贊助';
background-color: #d5d5d5;
color: #5e5e5e;
display: block;
padding: 0 2em;
border-radius: 50px;
font-size: 12px;
margin-left: auto;
width: 64px;
letter-spacing: 0;
}
除了透過外掛來新增自訂欄位外,我們也可以透過 WordPress 內建的函式 add_meta_box
來新增自訂欄位。詳細的解說可以參考另一位 Eric 的這篇文章。我們這邊直接以上述的 pr
為例:
function is_pr_register_meta( ) {
add_meta_box(
'this_is_pr', // 欄位 ID,必須是唯一值
'是否為贊助文章', // 自訂欄位的標題名稱
'is_pr_callback', // 呼叫函式,定義欲儲存的資料
'post', // 只在文章中顯示自訂欄位
'side'
);
}
add_action( 'add_meta_boxes', 'is_pr_register_meta' );
function is_pr_callback( $post ) {
$value = get_post_meta($post->ID, '_this_is_pr', true);
wp_nonce_field( 'is_pr_inner', 'is_pr_inner_nonce');
// 為 'is_pr_inner' 這個行為加密,產生一組單次通行的驗證碼 'is_pr_inner_nonce'
?>
<label for="this_is_pr">是贊助文章</label>
<input type="checkbox" id="this_is_pr" name="this_is_pr" class="postbox" value="1" <?php echo $value ? 'checked' : null ?>>
<?php }
function is_pr_save_meta( $post_id ) {
if ( ! isset( $_POST['is_pr_inner_nonce'] ) ) {
return $post_id; // 在儲存時如果沒有 'is_pr_inner_nonce',便無法儲存。
}
$nonce = $_POST['is_pr_inner_nonce'];
if ( ! wp_verify_nonce( $nonce, 'is_pr_inner' ) ) {
return $post_id;
// 在儲存時如果 'is_pr_inner_nonce' 與 is_pr_callback 產生的驗證碼不同
// 便無法儲存。
}
/*
* 避免系統的自動儲存去儲存自訂欄位的內容。
*/
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// 確認使用者權限
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
$data = $_POST['this_is_pr'];
update_post_meta( $post_id, '_this_is_pr', $data );
}
add_action( 'save_post', 'is_pr_save_meta' );
function eric_is_pr_meta( $classes, $class, $post_id ){
$class_list = [];
if ( get_post_meta( $post_id, '_this_is_pr' )[0] === "1" ) {
$class_list[] = 'is-pr';
}
return array_merge( $classes, $class_list );
}
add_filter( 'post_class', 'eric_is_pr_meta', 10, 3 );
// 利用 post_class 篩選器,加入 is-pr 這個類型
從上面的例子可以看出,透過 add_meta_box
的方式打造自訂欄位相當耗費時間,因此大多數的情況下,我都建議透過 ACF 來管理自訂欄位。除非你有下列三種考量:
自訂欄位搭配自訂內容類型後,可以將原本的 WordPress 進一步擴充到各種進階用途,譬如投影片輪播個別投影片的屬性、分店服務人員的基本資訊等。此外,就如同 SEO 外掛,我們也可以透過自訂欄位,替我們的自訂內容類型添加結構化資料。
下一章,我們將結合自訂欄位與自訂內容類型,介紹 WordPress 的迴圈 (loop) 功能。
Advanced Custom Fields 官方文件
Advanced Custom Fields
利用 add_meta_box 自行新增自訂欄位