Agregar múltiples meta-boxes a un tipo de publicación personalizada en wordpress

10 minutos de lectura

avatar de usuario
BIOS

Tengo el siguiente código que agrega un tipo de publicación personalizada al tablero de administración y un cuadro meta personalizado a la ventana de edición de publicaciones:

function teasers_custom_init() {
  $labels = array(
    'name' => 'Teasers',
    'singular_name' => 'Teaser',
    'add_new' => 'Add New',
    'add_new_item' => 'Add New Teasers',
    'edit_item' => 'Edit Teaser',
    'new_item' => 'New Teaser',
    'all_items' => 'All Teasers',
    'view_item' => 'View Teaser',
    'search_items' => 'Search Teasers',
    'not_found' =>  'No teasers found',
    'not_found_in_trash' => 'No teasers found in Trash', 
    'parent_item_colon' => 'Parent Page',
    'menu_name' => 'Teasers'
  );

  $args = array(
    'labels' => $labels,
    'description' => 'set slider panels with loop times',
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true, 
    'show_in_menu' => true, 
    'query_var' => true,
    'rewrite' => array( 'slug' => 'Teasers' ),
    'capability_type' => 'page',
    'has_archive' => true, 
    'hierarchical' => true,
    'menu_position' => 60,
    'supports' => array( 'title', 'thumbnail', 'page-attributes'), 

  ); 

  register_post_type( 'teasers', $args );
}
add_action( 'init', 'teasers_custom_init' );


//adding the meta box when the admin panel initialises
add_action("admin_init", "admin_init");
// this adds the save teaser function on save post
add_action('save_post', 'save_teaser');

function admin_init(){
    add_meta_box('teaser_loop', 'Loop Time', 'loop_meta', 'teasers', 'normal', 'default');
}
// callback function of add meta box that displays the meta box in the post edit screen
function loop_meta($post, $args){

    $teaser_loop = get_post_meta($post->ID, 'teaser_loop', true);

?>
    <label>Teaser Loop: </label><input type="text" name="teaser_loop" value="<?php echo $teaser_loop; ?>" /><br/>

<?php

}

// saving the teaser
function save_teaser(){
    global $post;
    update_post_meta($post->ID, 'teaser_loop', $_POST['teaser_loop']);  
}

Mi pregunta es si quiero agregar un metabox adicional, ¿cuál es el mejor enfoque?

Intenté agregar otra llamada add_meta_box en la función admin_init y también creé una función de devolución de llamada adicional para este metabox html, pero no se generó nada en la interfaz. Cualquier punto sería genial.

EDITAR: así es como lo hice para más de un cuadro meta (esto funciona):

//adding the meta box when the admin panel initialises
    add_action("admin_init", "admin_init");
    // this adds the save teaser function on save post
    add_action('save_post', 'save_teaser');
    function admin_init(){
        add_meta_box('teaser_loop', 'Loop Time', 'loop_meta_1', 'teasers', 'normal', 'default');
        add_meta_box('teaser_link', 'Teaser Link', 'loop_meta_2', 'teasers', 'normal', 'default');
    }
    // back function of add meta box that displays the meta box in the post edit screen
    function loop_meta_1($post, $args){


        $teaser_loop = get_post_meta($post->ID, 'teaser_loop', true);

?>
    <label>Teaser Loop: </label><input type="text" name="teaser_loop" value="<?php echo $teaser_loop; ?>" /><br/>

<?php

}

    function loop_meta_2($post, $args){

        $teaser_link = get_post_meta($post->ID, 'teaser_link', true);

?>
    <label>Teaser Link: </label><input type="text" name="teaser_link" value="<?php echo $teaser_link; ?>" /><br/>

<?php

}

// saving the teaser
function save_teaser(){
    global $post;
    update_post_meta($post->ID, 'teaser_loop', $_POST['teaser_loop']);
    update_post_meta($post->ID, 'teaser_link', $_POST['teaser_link']);
}

  • También puedes preguntar esto en wordpress.stackexchange.com

    – Joren

    7 oct 2013 a las 18:23

  • O en Revisión de códigoya que este es un código de trabajo que pretende optimizarse.

    – brasofilo

    7 oct 2013 a las 18:39


  • He puesto la recompensa porque en ninguna parte de la web hay un enfoque dinámico para este problema. Me preguntaba cuál sería la solución óptima que incorpora todos los elementos de forma.

    – Joren

    7 oct 2013 a las 18:47

  • Genial, esto es justo lo que estaba buscando. ¡Gracias!

    – Eco fantasma

    8 mayo 2017 a las 19:33

avatar de usuario
brasofilo

Se puede encapsular completamente en una clase. Aquí, no estoy tratando de agregar el Tipo de publicación personalizada, y solo hay dos campos de salida simples, texto y casilla de verificación. Un código de trabajo completo debe encargarse de cada uno de los tipos de entrada deseados.

<?php
/**
 * Plugin Name: Sample Dynamic Meta Boxes
 * Plugin URI:  http://stackoverflow.com/q/13903529/1287812
 * Author:      brasofilo
 */
class B5F_Dynamic_Meta_Boxes 
{
    private $boxes;

    # Safe to start up
    public function __construct( $args )
    {
        $this->boxes = $args;
        add_action( 'plugins_loaded', array( $this, 'start_up' ) );
    }

    public function start_up()
    {
        add_action( 'add_meta_boxes', array( $this, 'add_mb' ) );
    }

    public function add_mb()
    {
        foreach( $this->boxes as $box )
            add_meta_box( 
                $box['id'], 
                $box['title'], 
                array( $this, 'mb_callback' ), 
                $box['post_type'], 
                isset( $box['context'] ) ? $box['context'] : 'normal', 
                isset( $box['priority'] ) ? $box['priority'] : 'default', 
                $box['args']
            );
    }

    # Callback function, uses helper function to print each meta box
    public function mb_callback( $post, $box )
    {
        switch( $box['args']['field'] )
        {
            case 'textfield':
                $this->textfield( $box, $post->ID );
            break;
            case 'checkbox':
                $this->checkbox( $box, $post->ID );
            break;
        }
    }

    private function textfield( $box, $post_id )
    {
        $post_meta = get_post_meta( $post_id, $box['id'], true );
        printf(
            '<label>%s: <input type="text" name="%s" value="%s" /></label> <small>%s</small><br/>',
            $box['title'],
            $box['id'],
            $post_meta,
            $box['args']['desc']
        );
    }

    private function checkbox( $box, $post_id )
    {
        $post_meta = get_post_meta( $post_id, $box['id'], true );
        printf(
            '<label>%s: </label><input type="checkbox" name="%s" %s /> <small>%s</small><br/>',
            $box['title'],
            $box['id'],
            checked( 1, $post_meta, false ),
            $box['args']['desc']
        );
    }
}

# ADD TWO META BOXES - DIFFERENT POST TYPES - DIFFERENT CONTEXTS AND PRIORITIES
$args = array(
    array(
        'id' => 'teaser_loop',
        'title' => 'Loop Time',
        'post_type' => 'post',
        'args' => array(
            'desc' => 'Enter the time',
            'field' => 'textfield',
        )
    ),
    array(
        'id' => 'teaser_link',
        'title' => 'Loop Link',
        'post_type' => 'page',
        'context' => 'side',
        'priority' => 'high',
        'args' => array(
            'desc' => 'Open link',
            'field' => 'checkbox',
        )
    ),
);
new B5F_Dynamic_Meta_Boxes( $args );

# ADD ANOTHER META BOX TO ANOTHER POST TYPE
$more_args = array(
    array(
        'id' => 'extra_box',
        'title' => 'And another one',
        'post_type' => 'teaser',
        'args' => array(
            'desc' => 'Open link',
            'field' => 'textfield',
        )
    ),
);
new B5F_Dynamic_Meta_Boxes( $more_args );

Esto es solo un esqueleto, a partir de aquí hay mucho que escribir. Algunos ejemplos:

  • Esto se limita a la entrada de texto. Esto no funciona si está trabajando con casillas de verificación/radio, menús desplegables u otros elementos de formulario. Aunque la primera parte me gusta, pero parece un poco exagerada.

    – Joren

    7 oct 2013 a las 18:19


  • @Joren, bueno, es solo un esquema. Usar una clase sería más apropiado. Ajustarlo depende del usuario. No has puesto una descripción personalizada en la recompensa, ¿puedes publicar un comentario en la Pregunta indicando lo que esperas?

    – brasofilo

    7 oct 2013 a las 18:36

  • @brasofilo: ¿Es posible usar su class ¿Puedo agregar múltiples campos meta dentro de un solo cuadro meta y también puedo agregar la funcionalidad de pestaña allí?

    – Mayeenul Islam

    21 de junio de 2014 a las 14:25


  • @MayeenulIslam, puede adaptar lo siguiente: pt.stackoverflow.com/a/10564/201

    – brasofilo

    21 de junio de 2014 a las 16:02

Puede agregar metabox al tipo de publicación personalizada con el siguiente código.

Primero, crea metabox

add_action('admin_init', 'my_theme_on_admin_init');

function my_theme_on_admin_init() {
    add_meta_box('my_metabox',
        __('My metabox', 'textdomain'),
        'my_metabox_render',
        'my_custom_post_type', 'normal', 'high'
    );
}

Darse cuenta de my_custom_post_type es un nombre de su tipo de publicación personalizada y my_metabox_render – nombre de una función que representa metabox.

La función de representación debe crear todos los campos necesarios.

function my_metabox_render($post) {
    $data = get_post_meta($post->ID, '_meta_key', true);
    // Use nonce for verification
    wp_nonce_field('add_my_meta', 'my_meta_nonce');
?>
<div class="inside">
    <table class="form-table">
        <tr valign="top">
            <th scope="row"><label for="my_meta_value"><?php _e('My meta', 'textdomain'); ?></label></th>
            <td><textarea id="my_meta_value" name="my_meta_value" cols="40" rows="5"><?php echo (isset($data)) ? $data : ''; ?></textarea></td>
        </tr>
    </table>
</div>
<?php
}

De lo que debe actualizar sus metadatos cuando el usuario guarda la publicación

add_action('wp_insert_post', 'save_my_meta', 10, 2);

function save_my_meta($id) {
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
        return $id;
    if (!current_user_can('edit_posts'))
        return;

    if (!isset($id))
        $id = (int) $_REQUEST['post_ID'];

    if (isset($_POST['my_meta_value']) && wp_verify_nonce($_POST['my_meta_value'], 'add_my_meta')) {
        $data = $_POST['my_meta_value'];
        if (isset($data)) {
            update_post_meta($id, '_meta_key', $data);
        }
        else {
            delete_post_meta($id, '_meta_key');
        }
    }
}

  • Hola vladimir. Gracias por la respuesta. Agregar un cuadro meta está bien, pero ¿cómo agrego más de un cuadro meta a un tipo de publicación personalizada? Ese es el problema que estoy teniendo.

    – BIOS

    16 de diciembre de 2012 a las 18:25

  • Llamar add_meta_box función para cada cuadro meta que desea crear. Y, por supuesto, cada cuadro meta debe tener su propia función de representación.

    – Vladímir

    16 de diciembre de 2012 a las 19:42

  • ¿Podría mostrar el código que está tratando de agregar varios metaboxes?

    – Vladímir

    16 de diciembre de 2012 a las 19:52


  • Código agregado para agregar dos y esto ahora funciona. No estoy seguro si es la mejor manera, pero funciona para mí.

    – BIOS

    21 de diciembre de 2012 a las 0:09

¿Es esta una forma muy incorrecta de agregar 2 metaboxes? Funciona, pero creo que puede ser código/php ineficiente. El original fue publicado en https://typerocket.com

// Add form and basic text field
function press_meta_box(WP_Post $post) {
    add_meta_box('press_meta', 'Press Release Date', function() use ($post) {
        $field_name="press_date";
        $field_name2 = 'press_link';
        $field_value = get_post_meta($post->ID, $field_name, true);
        $field_value2 = get_post_meta($post->ID, $field_name2, true);
        wp_nonce_field('study_nonce', 'study_nonce');
        ?>
        <table class="form-table">
            <tr>
                <th> <label for="<?php echo $field_name; ?>">Press Release Date (MM/DD/YYYY)</label></th>
                <td>
                    <input id="<?php echo $field_name; ?>"
                           name="<?php echo $field_name; ?>"
                           type="text"
                           value="<?php echo esc_attr($field_value); ?>" />
                </td>
            </tr>
            <tr>
                <th> <label for="<?php echo $field_name2; ?>">Full link to pdf</label></th>
                <td>
                    <input id="<?php echo $field_name2; ?>"
                           name="<?php echo $field_name2; ?>"
                           type="text"
                           value="<?php echo esc_attr($field_value2); ?>" />
                </td>
            </tr>
        </table>
        <?php
    });
}
// Check for empty string allowing for a value of `0`
function empty_str( $str ) {
    return ! isset( $str ) || $str === "";
}
// Save and delete meta but not when restoring a revision
add_action('save_post', function($post_id){
    $post = get_post($post_id);
    $is_revision = wp_is_post_revision($post_id);
    $field_name="press_date";
    $field_name2 = 'press_link';

    // Do not save meta for a revision or on autosave
    if ( $post->post_type != 'press_release' || $is_revision )
        return;

    // Do not save meta if fields are not present,
    // like during a restore.
    if( !isset($_POST[$field_name]) )
        return;

    // Secure with nonce field check
    if( ! check_admin_referer('study_nonce', 'study_nonce') )
        return;

    // Clean up data
    $field_value = trim($_POST[$field_name]);
$field_value2 = trim($_POST[$field_name2]);
    // Do the saving and deleting
    if( ! empty_str( $field_value ) ) {
        update_post_meta($post_id, $field_name, $field_value);
    } elseif( empty_str( $field_value ) ) {
        delete_post_meta($post_id, $field_name);
    }
     // Do the saving and deleting 2
    if( ! empty_str( $field_value2 ) ) {
        update_post_meta($post_id, $field_name2, $field_value2);
    } elseif( empty_str( $field_value2 ) ) {
        delete_post_meta($post_id, $field_name2);
    }
});

¿Ha sido útil esta solución?