Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
內容目錄
為了讓客戶可以在頁面層級加入要使用的 MW WP Form ID,同時想要跳過學習 ACF 以外的技能,所以使用 add_meta_box 來增加自訂欄位。
註冊欄位需要使用 add_meta_boxes 這個勾點(有關勾點的介紹,可以參考這篇文章)。
根據官方的開發者文件,add_meta_boxes 這個勾點中,需要透過 add_meta_box 這個函式,將欲註冊的欄位資訊填入:
add_meta_box(
‘註冊 ID (須唯一,避免與其他外掛衝突)‘,
‘欄位標題 (顯示於編輯頁中)’,
‘回傳函式 (也可以直接寫 function(){}),設定欄位樣式用’,
‘欲註冊的文章類型,可以是陣列’,
‘位置,side 代表在側邊’);
<?php function reservation_register_meta( ) { global $post; if ( 'page-shopreservations.php' != get_post_meta( $post->ID , '_wp_page_template', true ) ) { return; } else { add_meta_box( 'reservation-form-id', 'MW WP Form ID', 'reservation_meta_callback', 'page', 'side' ); } } add_action( 'add_meta_boxes', 'reservation_register_meta' );
這裡還使用了 global $post 的全域變數,用來判斷只在特定的文章範本 (page-shopreservations.php) 中才會顯示自訂欄位。跟 ACF 的邏輯判斷一樣。
在步驟一中,add_meta_box 的第三個參數是回傳函式,我們要在這裡設定自訂欄位的樣式。
首先設定 $value 這組變數,用來查詢這篇文章是否已經存有自訂欄位的值。為了避免欄位值被注入怪怪的程式碼,因此使用 esc_attr 進行迴避。
function reservation_meta_callback( $post ) { $value = get_post_meta( $post->ID, '_reservation_id', true); wp_nonce_field( 'reservation_inner', 'reservation_inner_nonce'); ?> <label for="reservation_id">ID of MW WP Form</label> <input type="text" id="reservation_id" name="reservation_id" class="postbox" value="<?php echo esc_attr( $value );?>"> <?php }
這邊需要注意的地方是 wp_nonce_field 這個函式,nonce 在密碼學中是一組「只用一次」的加密數字 (a “number” that can be used only “once”),在這裡是用來確保資料只能透過這裡的表單傳遞,避免有心人士透過程式碼鑽漏洞,是在 WordPress 中必要的基本防護措施。
這裡使用 wp_nonce_field( ‘reservation_inner’, ‘reservation_inner_nonce’ ); 這個函式,定義將 ‘reservation_inner’ 這個行為進行加密,產生一組名為 reservation_inner_nonce 的 nonce。
最後這個步驟較為複雜,是參考 WordPress 官方文件寫的。
在將自訂欄位的資料存入 save_post 這個鉤點以前,先檢查是否有 reservation_inner_nonce,並進一步檢查 reservation_inner_nonce 是否與我們定義的 reservation_inner 這個動作發生在同一個工作階段。
function reservation_save_meta( $post_id ) { if ( !isset( $_POST['reservation_inner_nonce'] ) ) { return $post_id; } $nonce = $_POST['reservation_inner_nonce']; if ( !wp_verify_nonce( $nonce, 'reservation_inner' ) ) { return $post_id; } /* * If this is an autosave, our form has not been submitted, * so we don't want to do anything. */ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return $post_id; } // Check the user's permissions. if ( 'page' == $_POST['post_type'] ) { if ( ! current_user_can( 'edit_page', $post_id ) ) { return $post_id; } } else { if ( ! current_user_can( 'edit_post', $post_id ) ) { return $post_id; } } $data = sanitize_text_field( $_POST['reservation_id'] ); update_post_meta( $post_id, '_reservation_id', $data ); } add_action( 'save_post', 'reservation_save_meta' );
第二段在避免文章在自動儲存時,將自訂欄位值存入。第三段則是確保使用者有編輯文章或頁面的權限。最後透過 sanatize_text_field 來避免跨網站指令碼 (XSS,Cross-site Scripting) 的攻擊。
最後透過 update_post_meta 這個函式,在儲存文章時,將 name 屬性值為 reservation_id 的值同時存入 _reservation_id 這個中繼資料 (meta data) 裡。
將上面三個步驟全部組合起來之後就如下:
<?php function reservation_register_meta( ) { global $post; if ( 'page-shopreservations.php' != get_post_meta( $post->ID , '_wp_page_template', true ) ) { return; } else { add_meta_box( 'reservation-form-id', 'MW WP Form ID', 'reservation_meta_callback', 'page', 'side' ); } } add_action( 'add_meta_boxes', 'reservation_register_meta' ); function reservation_meta_callback( $post ) { $value = get_post_meta($post->ID, '_reservation_id', true); wp_nonce_field( 'reservation_inner', 'reservation_inner_nonce'); ?> <label for="reservation_id">ID of MW WP Form</label> <input type="text" id="reservation_id" name="reservation_id" class="postbox" value="<?php echo esc_attr( $value );?>"> <?php } function reservation_save_meta( $post_id ) { if ( !isset( $_POST['reservation_inner_nonce'] ) ) { return $post_id; } $nonce = $_POST['reservation_inner_nonce']; if ( !wp_verify_nonce( $nonce, 'reservation_inner' ) ) { return $post_id; } /* * If this is an autosave, our form has not been submitted, * so we don't want to do anything. */ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return $post_id; } // Check the user's permissions. if ( 'page' == $_POST['post_type'] ) { if ( ! current_user_can( 'edit_page', $post_id ) ) { return $post_id; } } else { if ( ! current_user_can( 'edit_post', $post_id ) ) { return $post_id; } } $data = sanitize_text_field( $_POST['reservation_id'] ); update_post_meta( $post_id, '_reservation_id', $data ); } add_action( 'save_post', 'reservation_save_meta' );
自己實作了一次之後,更能了解 ACF 這款外掛是何等強大。上面整串程式碼,使需要透過幾個步驟點擊,就可以用 1/10 的時間透過 ACF 完成這項任務。尤其 ACF Pro 支援複雜的條件式,以及重複欄位 (repeated fields) 等進階功能,大多數的狀況,真的不建議自己實作出來。
至於什麼樣的情況之下,會選用非 ACF 的方式來實作自訂欄位呢?我認為大概有這三個原因:
除了上面的 3 種情形外,我認為如果要實作自訂欄位的話,ACF 還是比較好的選擇,畢竟都選用 WordPress 了,當然要盡量避免重新造輪的情況嘍!