iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
1
自我挑戰組

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

Day 23 WordPress 的自訂欄位 (custom fields)

  • 分享至 

  • xImage
  •  

大家好,我是 Eric。

昨天我們介紹完 WordPress 的自訂內容類型,今天我們要再進一步介紹客製化的另一個環節:自訂欄位。我們在昨天的內容曾提到使用自訂欄位的情境:

附屬於個別內容的中繼資料 (meta data),譬如說各分店的地址與聯絡方式。

以我們常見的 SEO 外掛來說,當你安裝 SEO 外掛後,你在編輯文章時,便會出現其他欄位,可以讓你填寫不同的中繼資料,如頁面的標題、敘述,甚至是社群網路的中繼資料 (如 Open Graph 標記)。

在 WordPress 中新增自訂欄位:ACF

和自訂內容類型一樣,自訂欄位也能透過外掛來管理。其中,使用最為廣泛的,便是 Advanced Custom Fields (俗稱「ACF」) 這款外掛。透過 ACF,我們可以藉由介面直接管理自訂欄位。

管理自訂欄位

在免費版的 ACF 中,有 32 種欄位可供選擇使用,這裡簡介幾種常見的欄位:

欄位名稱 | 說明
-------+-------
文字 (Text) | 用來儲存單行文字,譬如 SEO 外掛中的「標題」。
文字區域 (Text area) | 用來儲存多行文字,譬如 SEO 外掛中的「敘述」。
圖片 (Image) | 可以用來上傳圖片,並回傳圖片物件或陣列。
日期選擇器 (Date Picker) | 可以用來儲存特定日期,可用於自訂文章有效期限 (例如促銷)。
文章物件 (Post Object) | 可以用來關聯一系列的內容 (post)。

關於「文章物件」,可以特別提出來說一下。在昨天的文章中,我們曾提到 WordPress 將所有內容都當成文章的做法,讓文章之間的關聯變得較困難。其中一種方法,就是透過文章物件來建立內容間的關聯。實際的作法,我們會在之後的實務操作中再說明。

取得 ACF 的欄位資料

取得 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;
}

透過 add_meta_box 新增自訂欄位

除了透過外掛來新增自訂欄位外,我們也可以透過 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 來管理自訂欄位。除非你有下列三種考量:

  • 只需要單一欄位,不希望為了單一欄位安裝整個 ACF 外掛:ACF 的功能強大,但是很多時候你的網站可能並不需要這麼多自訂欄位。如果你只是希望新增單一欄位的話,自己實作會是一個不錯的選擇。
  • 想要開發免費外掛/佈景主題,免費的 ACF 功能卻無法滿足進階需求。根據 ACF 的授權,如果是付費的外掛或是佈景主題,開發者可以將原始碼中引入 ACF Pro 的原始碼,進行再開發,但開發者不得在免費外掛或佈景主題中引入 ACF Pro。
  • 想要開發外掛/佈景主題,但是希望降低與其他外掛的相依性。這部分可能比較跟開發者的習慣有關,有些開發者希望盡量讓自己的外掛或佈景主題,不要依靠其他第三方的功能,便會使用這個方法。

結語

自訂欄位搭配自訂內容類型後,可以將原本的 WordPress 進一步擴充到各種進階用途,譬如投影片輪播個別投影片的屬性、分店服務人員的基本資訊等。此外,就如同 SEO 外掛,我們也可以透過自訂欄位,替我們的自訂內容類型添加結構化資料。
下一章,我們將結合自訂欄位與自訂內容類型,介紹 WordPress 的迴圈 (loop) 功能。

延伸閱讀

Advanced Custom Fields 官方文件
Advanced Custom Fields
利用 add_meta_box 自行新增自訂欄位


上一篇
Day 22 客製化 WordPress 的精髓:內容類型 (post type)
下一篇
Day 24 WordPress 客製化取用資料的基本手段:迴圈 (loop)
系列文
WordPress 客製化從 0 開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言