如何應用WordPress的自訂區塊(Meta Box)和自訂欄位(Custom Fields)?
| 2011/03/30 | 3 則迴響
什麼是自訂欄位?
所謂的自訂欄位(Custom Fields)是指WordPress內建的自訂欄位功能(見圖),它能讓每篇文章都附掛一些屬於該文章的自訂資料,例如你希望儲存每篇文章的英文標題,以便能在前端佈景中呈現出來,開發者就能設計一個自訂欄位來儲存該篇文章的英文標題。於是使用者就能在後台建立文章時,利用自訂欄位來設定英文標題,或進行更多其他資料的擴充。而且自訂欄位不受限於內容型別,也就是說除了內建的文章(Post)、網誌分頁(Page)…等,也能使用自訂的內容型別。
自訂欄位能讓開發人員可以預先自訂最多30組由「名稱」對應「值」的文字框欄位,提供給使用者或程式去存取,當然也不一定限於要在後台寫入,寫入的時間點可以是任何的Hook時間點,就看你想做出什麼樣的功能。常見的運用是在後台由使用者存好自訂資料後發佈,就能在前台輸出佈景時,隨著取出該文章的內容時,也取出其附掛的自訂資料來做出一些功能或特效。常見的應用像是計算每篇文章的瀏覽次數、存放縮圖路徑…等,都是自訂欄位的應用。
為何要使用自訂區塊(meta box)來包裝自訂欄位?
直接使用自訂欄位的相關Function,對開發人員來說快速又方便,如add_post_meta、update_post_meta及delete_post_meta等,缺點是使用者必須將就一點,使用預設的UI,而且還需要「聰明」一點,需要知道每個特定的自訂欄位有什麼特殊效果,何況要達成某些效果,有些還要設定多個自訂欄位。因此如果後台要提供給新手使用者操作,看到自訂欄位預設的UI,可能會覺得很醜或覺得難用。
要改善自訂欄位的使用性問題,我們可以透過建立自訂區塊(Meta Box)來「包裝」一下自訂欄位的UI。是的,Meta Box骨子裡還是用自訂欄位相關的操作Function來存取設定值。使用Meta Box可讓開發人員建立自訂的區塊,如此可達成包裝原本自訂欄位的UI,您可以放文字框、下拉方塊、勾選鈕…等,甚至是一個所見即所得的編輯介面(Editor)都行,讓後台能擁有更友善的操作介面。
實例應用說明
文章一開始提到的「英文選單標題」的例子,很適合當成範例說明,我們就來看看怎麼應用Meta Box吧,要試試看的話,首先打開您佈景中的functions.php,加入以下程式:
[code lang=”php”]
/* 小範例:建立英文選單標題 */
add_action(‘admin_init’, ‘admin_init_fn’); // 指定後台初始化時要執行我們自訂的函式admin_init_fn
function admin_init_fn() {
// 使用add_meta_box來增加一個「自訂區塊」,在callback的參數位置,放上我們自訂的函式 EnTitleCB_fn
add_meta_box(‘EnTitle’, ‘英文標題’, ‘EnTitleCB_fn’, ‘page’, ‘normal’, ‘high’, null);
}
function EnTitleCB_fn() {
// 需要取得目前編輯的post資訊,如id
global $post;
// 如果是進入編輯模式,WP會POST資料進來
$entitle_cnt = get_post_meta( $post->ID, ‘EnTitle’, true );
?>
<th scope=”row”>主選單英文標題:</th>
<td>
<label for=”EnTitle”>
<input id=”EnTitle” type=”text” size=”75″ name=”EnTitle” value=”<?php echo $entitle_cnt;?>” />
<br /><em>說明:設定分頁出現在選單時的英文翻譯。</em>
</label>
</td>
</tr>
<?php
}
[/code]
加入上述程式碼,WP會在後台初始化時呼叫我們寫的函式admin_init_fn,然後發現我們寫了一個add_meta_box,就為我們在後台加上一個自訂區塊叫「英文標題」,並且依照我們給的CallBack函式定義,輸出自訂區塊的外觀。
是的,目前只有「外觀」! 如果真的輸入值,按下「更新」,還是無法被儲存,因為我們還要在使用者儲存文章時,一併的把我們的值也存起來,所以還要在functions.php加上一些程式碼:
[code lang=”php”]
add_action(‘wp_insert_post’, ‘insert_post_fn’, 10, 2); // 讓WP在新增文章內容時,也執行我們定義的insert_post_fn
function insert_post_fn($post_id, $post = null) {
$meta_post_fields = array(“EnTitle”); // EnTitle是我們定義的input的name
$goloop = false;
// 如果是我們要處理的內容型別-page (讓自訂的meta box只出現在網誌分頁裡的文章)
if ($post->post_type == “page”) {
$mfs = $meta_post_fields;
$goloop = true;
}
if ($goloop) {
// 取得Post進來的欄位資料,針對我們自訂的欄位$meta_fields
foreach ($mfs as $key) {
// 如果有空值就不進行處理
$value = @$_POST[$key];
if (empty($value)) {
delete_post_meta($post_id, $key);
continue;
}
// 如果丟過來的參數不是陣列
if (!is_array($value)) {
// 更新資料,若無法更新,代表是要新增資料
if (!update_post_meta($post_id, $key, $value)) {
add_post_meta($post_id, $key, $value);
}
}else{
// 如果丟過來的參數是陣列,先刪除之前的值,再一個個建進相同名稱的post meta
delete_post_meta($post_id, $key);
// Loop through the array adding new values to the post meta as different entries with the same name
foreach ($value as $entry) {
add_post_meta($post_id, $key, $entry);
}
}
}
}
}
[/code]
我們從meta box裡面的input所丟出來的值也可能是陣列,但這有機會再介紹。加入上述的程式碼,最後我們就能得到如下圖的結果,值也能存起來,不過因為我們使用了add_post_meta來幫助我們把值存在自訂欄位中,所以我們存的值也會自動出現在自訂欄位裡。
覺得自訂欄位區塊很多餘嗎?加入以下的程式碼,就可以移除它囉!
[code lang=”php”]
function remove_post_custom_fields() {
remove_meta_box( ‘postcustom’ , ‘post’ , ‘normal’ );
}
add_action( ‘admin_menu’ , ‘remove_post_custom_fields’ );
[/code]
成功的使用add_post_meta儲存每篇文章的自訂資料後,我們就可以在前台使用get_post_meta把我們在每篇文章存的值取出來用,只要指定post id和欄位名稱就可以把對應的值取出來囉,是不是很方便呢?
如此您也能打造一個專業又好用的WP客製介面!
標籤:WordPress, WordPress開發
本文作者是Audi Lu
3 則留言
我文章沒有自訂欄位這個功能
http://dl.dropbox.com/u/23050296/a.jpg
請問要如何開啟
Hi soon, 請到同一個畫面的右上方,有個「顯示選項」,點下後,就會出現很多勾選項目,其中就有「自訂欄位」,打勾就會出現了。
請問我只需要在自定欄位下拉式選單出現”Image”,欄位內容由我自行輸入
請教您,我改如何設定呢?謝謝。
輸入後,要怎麼取這個Image欄位的值呢?謝謝。