所谓 WordPress metabox,就是类似文章编辑框下面 WP 自带的自定义字段的设置面板,通过 add_meta_box() 可以添加自定义面板,方便地输入相关信息,并在前端调用实现一些功能。
基本的面板添加代码网上很多,本文分享两个可重复使用的自定义 metabox 字段面板。
代码一
预设两个字段,可重复添加,并以组数存储在数据库 wp_postmeta 表中
- add_action('admin_init', 'add_meta_boxes', 1);
- function add_meta_boxes() {
- add_meta_box( 'repeatable-fields', 'Audio Playlist', 'repeatable_meta_box_display', 'post', 'normal', 'high');
- }
- function repeatable_meta_box_display() {
- global $post;
- $repeatable_fields = get_post_meta($post->ID, 'repeatable_fields', true);
- wp_nonce_field( 'repeatable_meta_box_nonce', 'repeatable_meta_box_nonce' );
- ?>
- <script type="text/javascript">
- jQuery(document).ready(function($) {
- $('.metabox_submit').click(function(e) {
- e.preventDefault();
- $('#publish').click();
- });
- $('#add-row').on('click', function() {
- var row = $('.empty-row.screen-reader-text').clone(true);
- row.removeClass('empty-row screen-reader-text');
- row.insertBefore('#repeatable-fieldset-one tbody>tr:last');
- return false;
- });
- $('.remove-row').on('click', function() {
- $(this).parents('tr').remove();
- return false;
- });
- $('#repeatable-fieldset-one tbody').sortable({
- opacity: 0.6,
- revert: true,
- cursor: 'move',
- handle: '.sort'
- });
- });
- </script>
- <table id="repeatable-fieldset-one" width="100%">
- <thead>
- <tr>
- <th width="2%"></th>
- <th width="30%">Name</th>
- <th width="60%">URL</th>
- <th width="2%"></th>
- </tr>
- </thead>
- <tbody>
- <?php
- if ( $repeatable_fields ) :
- foreach ( $repeatable_fields as $field ) {
- ?>
- <tr>
- <td><a class="button remove-row" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >-</a></td>
- <td><input type="text" class="widefat" name="name[]" value="<?php if($field['name'] != '') echo esc_attr( $field['name'] ); ?>" /></td>
- <td><input type="text" class="widefat" name="url[]" value="<?php if ($field['url'] != '') echo esc_attr( $field['url'] ); else echo 'http://'; ?>" /></td>
- <td><a class="sort">|||</a></td>
- </tr>
- <?php
- }
- else :
- // show a blank one
- ?>
- <tr>
- <td><a class="button remove-row" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >-</a></td>
- <td><input type="text" class="widefat" name="name[]" /></td>
- <td><input type="text" class="widefat" name="url[]" value="http://" /></td>
- <td><a class="sort">|||</a></td>
- </tr>
- <?php endif; ?>
- <!-- empty hidden one for jQuery -->
- <tr class="empty-row screen-reader-text">
- <td><a class="button remove-row" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >-</a></td>
- <td><input type="text" class="widefat" name="name[]" /></td>
- <td><input type="text" class="widefat" name="url[]" value="http://" /></td>
- <td><a class="sort">|||</a></td>
- </tr>
- </tbody>
- </table>
- <p><a id="add-row" class="button" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Add another</a>
- <input type="submit" class="metabox_submit" value="Save" />
- </p>
- <?php
- }
- add_action('save_post', 'repeatable_meta_box_save');
- function repeatable_meta_box_save($post_id) {
- if ( ! isset( $_POST['repeatable_meta_box_nonce'] ) ||
- ! wp_verify_nonce( $_POST['repeatable_meta_box_nonce'], 'repeatable_meta_box_nonce' ) )
- return;
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
- return;
- if (!current_user_can('edit_post', $post_id))
- return;
- $old = get_post_meta($post_id, 'repeatable_fields', true);
- $new = array();
- $names = $_POST['name'];
- $urls = $_POST['url'];
- $count = count( $names );
- for ( $i = 0; $i < $count; $i++ ) {
- if ( $names[$i] != '' ) :
- $new[$i]['name'] = stripslashes( strip_tags( $names[$i] ) );
- if ( $urls[$i] == 'http://' )
- $new[$i]['url'] = '';
- else
- $new[$i]['url'] = stripslashes( $urls[$i] ); // and however you want to sanitize
- endif;
- }
- if ( !empty( $new ) && $new != $old )
- update_post_meta( $post_id, 'repeatable_fields', $new );
- elseif ( empty($new) && $old )
- delete_post_meta( $post_id, 'repeatable_fields', $old );
- }
前端调用
- <?php $repeatable_fields = get_post_meta( $post->ID, 'repeatable_fields', true ); if ( $repeatable_fields ) : ?>
- <div class="list">
- <?php foreach ( $repeatable_fields as $field ) { ?>
- <div class="row">
- <?php if( $field['name'] != '' ) echo '<span class="field">'. esc_attr( $field['name'] ) . '</span>'; ?>
- <?php if( $field['url'] != '' ) echo '<span class="field">'. esc_attr( $field['url'] ) . '</span>'; ?>
- </div>
- <?php } ?>
- </div>
- <?php endif; ?>
代码二
在上面的基础上,附加了下拉选项字段。
- function hhs_get_sample_options() {
- $options = array (
- 'Option 1' => 'option1',
- 'Option 2' => 'option2',
- 'Option 3' => 'option3',
- 'Option 4' => 'option4',
- );
- return $options;
- }
- add_action('admin_init', 'hhs_add_meta_boxes', 1);
- function hhs_add_meta_boxes() {
- add_meta_box( 'repeatable-fields', 'Repeatable Fields', 'hhs_repeatable_meta_box_display', 'post', 'normal', 'default');
- }
- function hhs_repeatable_meta_box_display() {
- global $post;
- $repeatable_fields = get_post_meta($post->ID, 'repeatable_fields', true);
- $options = hhs_get_sample_options();
- wp_nonce_field( 'hhs_repeatable_meta_box_nonce', 'hhs_repeatable_meta_box_nonce' );
- ?>
- <script type="text/javascript">
- jQuery(document).ready(function( $ ){
- $( '#add-row' ).on('click', function() {
- var row = $( '.empty-row.screen-reader-text' ).clone(true);
- row.removeClass( 'empty-row screen-reader-text' );
- row.insertBefore( '#repeatable-fieldset-one tbody>tr:last' );
- return false;
- });
- $( '.remove-row' ).on('click', function() {
- $(this).parents('tr').remove();
- return false;
- });
- });
- </script>
- <table id="repeatable-fieldset-one" width="100%">
- <thead>
- <tr>
- <th width="40%">Name</th>
- <th width="12%">Select</th>
- <th width="40%">URL</th>
- <th width="8%"></th>
- </tr>
- </thead>
- <tbody>
- <?php
- if ( $repeatable_fields ) :
- foreach ( $repeatable_fields as $field ) {
- ?>
- <tr>
- <td><input type="text" class="widefat" name="name[]" value="<?php if($field['name'] != '') echo esc_attr( $field['name'] ); ?>" /></td>
- <td>
- <select name="select[]">
- <?php foreach ( $options as $label => $value ) : ?>
- <option value="<?php echo $value; ?>"<?php selected( $field['select'], $value ); ?>><?php echo $label; ?></option>
- <?php endforeach; ?>
- </select>
- </td>
- <td><input type="text" class="widefat" name="url[]" value="<?php if ($field['url'] != '') echo esc_attr( $field['url'] ); else echo 'http://'; ?>" /></td>
- <td><a class="button remove-row" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Remove</a></td>
- </tr>
- <?php
- }
- else :
- // show a blank one
- ?>
- <tr>
- <td><input type="text" class="widefat" name="name[]" /></td>
- <td>
- <select name="select[]">
- <?php foreach ( $options as $label => $value ) : ?>
- <option value="<?php echo $value; ?>"><?php echo $label; ?></option>
- <?php endforeach; ?>
- </select>
- </td>
- <td><input type="text" class="widefat" name="url[]" value="http://" /></td>
- <td><a class="button remove-row" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Remove</a></td>
- </tr>
- <?php endif; ?>
- <!-- empty hidden one for jQuery -->
- <tr class="empty-row screen-reader-text">
- <td><input type="text" class="widefat" name="name[]" /></td>
- <td>
- <select name="select[]">
- <?php foreach ( $options as $label => $value ) : ?>
- <option value="<?php echo $value; ?>"><?php echo $label; ?></option>
- <?php endforeach; ?>
- </select>
- </td>
- <td><input type="text" class="widefat" name="url[]" value="http://" /></td>
- <td><a class="button remove-row" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Remove</a></td>
- </tr>
- </tbody>
- </table>
- <p><a id="add-row" class="button" href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >Add another</a></p>
- <?php
- }
- add_action('save_post', 'hhs_repeatable_meta_box_save');
- function hhs_repeatable_meta_box_save($post_id) {
- if ( ! isset( $_POST['hhs_repeatable_meta_box_nonce'] ) ||
- ! wp_verify_nonce( $_POST['hhs_repeatable_meta_box_nonce'], 'hhs_repeatable_meta_box_nonce' ) )
- return;
- if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
- return;
- if (!current_user_can('edit_post', $post_id))
- return;
- $old = get_post_meta($post_id, 'repeatable_fields', true);
- $new = array();
- $options = hhs_get_sample_options();
- $names = $_POST['name'];
- $selects = $_POST['select'];
- $urls = $_POST['url'];
- $count = count( $names );
- for ( $i = 0; $i < $count; $i++ ) {
- if ( $names[$i] != '' ) :
- $new[$i]['name'] = stripslashes( strip_tags( $names[$i] ) );
- if ( in_array( $selects[$i], $options ) )
- $new[$i]['select'] = $selects[$i];
- else
- $new[$i]['select'] = '';
- if ( $urls[$i] == 'http://' )
- $new[$i]['url'] = '';
- else
- $new[$i]['url'] = stripslashes( $urls[$i] ); // and however you want to sanitize
- endif;
- }
- if ( !empty( $new ) && $new != $old )
- update_post_meta( $post_id, 'repeatable_fields', $new );
- elseif ( empty($new) && $old )
- delete_post_meta( $post_id, 'repeatable_fields', $old );
- }
前端调用
- <?php $repeatable_fields = get_post_meta( $post->ID, 'repeatable_fields', true ); if ( $repeatable_fields ) : ?>
- <div class="list">
- <?php foreach ( $repeatable_fields as $field ) { ?>
- <div class="row">
- <?php if( $field['name'] != '' ) echo '<span class="field">'. esc_attr( $field['name'] ) . '</span>'; ?>
- <?php if( $field['select'] != '' ) echo '<span class="field">'. esc_attr( $field['select'] ) . '</span>'; ?>
- <?php if( $field['url'] != '' ) echo '<span class="field">'. esc_attr( $field['url'] ) . '</span>'; ?>
- </div>
- <?php } ?>
- </div>
- <?php endif; ?>