¿Cómo guardo metadatos solo para un tipo de publicación personalizado específico?

16

Estoy tratando de configurar un tipo de publicación personalizada siguiendo este tutorial . Sin embargo, estoy un poco confundido sobre cómo / dónde implementar update_post_meta(). El tutorial sugiere este patrón:

add_action('save_post', 'save_my_metadata');

function save_my_metadata()
{
    global $post;
    update_post_meta($post->ID, 'my_metadata', $_POST['my_metadata']);
}

Lo que funciona, pero tiene el desafortunado efecto de agregar esos metadatos a cada publicación, ya sea que pertenezca a este tipo personalizado o no.

Puse lo anterior functions.phpy supongo que podría ser parte del problema. Supongo que necesito restringir la acción 'save_post' para que solo se active para publicaciones de mi tipo personalizado.

Bobby Jack
fuente
Buena pregunta, Bobby Jack, pero ¿puedo pedirle que retitule la pregunta a algo como "Cómo guardar solo metadatos para tipos de publicaciones personalizadas específicas"; ya que su título es demasiado genérico para que las personas lo reconozcan cuando buscan una solución a este problema.
MikeSchinkel
@ Mike: hecho (totalmente de acuerdo con tu sugerencia, ¡gracias!)
Bobby Jack

Respuestas:

18
function save_my_metadata($ID = false, $post = false)
{
    if($post->post_type != 'your_post_type')
        return;
    update_post_meta($ID, 'my_metadata', $_POST['my_metadata']);
}

Eso debería funcionar. Simplemente reemplace 'your_post_type' con el nombre del tipo de publicación. Además, hecho poco conocido: el gancho 'save_post' pasa la identificación de la publicación como argumento.

EDITAR

Actualicé la función para reflejar el comentario de Jan. Gracias Jan!

John P Bloch
fuente
1
Incluso agrega la publicación en sí como el segundo argumento , por lo que no necesita usar la variable global.
Jan Fabry
Esta solución funciona ... La he usado antes en proyectos de clientes con mucho éxito.
EAMann
Brillante: funciona como un encanto. Y supongo que tendría sentido hacer "if ($ post-> post_type == 'animal') {update_post_meta ($ ID," number_of_legs ", $ _POST ['number_of_legs']);} else if ($ post-> post_type == 'vehicle') {update_post_meta ($ ID, "number_of_wheels", $ _POST ['number_of_wheels']);} // ... etc ... para manejar varios tipos de publicaciones diferentes? pobres capacidades de formato de comentarios!)
Bobby Jack
En realidad, con múltiples tipos de publicación, recomendaría usar una declaración de cambio en su lugar. Menos marcado, rendimiento más rápido, más fácil agregar casos en el futuro.
EAMann
@EAMann - sí, a mitad de escribir eso, me di cuenta de que un cambio sería mejor, pero los comentarios no son el lugar ideal para comenzar a editar el código, así que me volví flojo;)
Bobby Jack
4

Si desea manejar varios tipos de publicaciones, le recomiendo una declaración básica de cambio:

add_action('save_post', 'save_my_metadata');

function save_my_metadata($ID = false, $post = false)
{
    switch($post->post_type) 
    {
        case 'post_type_1':
            // Do stuff for post type 1
            update_post_meta($ID, 'my_metadata', $_POST['my_metadata']); // Example...
            break;
        case 'post_type_2':
            // Do stuff for post type 2
            break;
        default:
            return;
    }
}

Los casos son básicamente los mismos que if($post->post_type) == 'post_type_1') {}Pero no requieren múltiples bloques if-else. El defaultbloque en el interruptor maneja casos en los que el tipo de publicación no está en su conjunto personalizado.

EAMann
fuente
4

@John P Bloch y @EAMann ya han dado excelentes respuestas, así que la mía es además:

  1. Considere prefijar sus meta_keys con un guión bajo . Al hacerlo, los oculta de la lista de campos personalizados que se muestran en una pantalla de edición posterior, es decir

    función save_my_metadata ($ post_id, $ post = false) {
       if ($ post-> post_type == 'your_post_type')
          update_post_meta ($ post_id, '_my_metadata', $ _POST ['my_metadata']);
    }
    
    Obviamente, eso significa que necesitaría un metabox personalizado para poder editar los campos también. Aquí hay una pantalla de edición para el contexto:



  2. Otra cosa que puede hacer es agregar su propio enlace para facilitar el guardado de tipos de publicación específicos, es decir, su enlace podría ser " save_{$post_type}_post"; para un movietipo de publicación sería save_movie_post. Esto es lo que tendría que agregar al functions.phparchivo de su tema o en un complemento en alguna parte:

    add_action ('save_post', 'save_custom_post_type_posts', 10,2);
    función save_custom_post_type_posts ($ post_id, $ post = false) {
       do_action ("guardar _ {$ post-> post_type} _post");
    }
    
    Con eso, podría volver a escribir su código original de esta manera (incluido el truco de subrayado del n. ° 1 anterior):

    add_action ('save_my_postype_post', 'save_my_postype_metadata', 10,2);
    función save_my_postype_metadata ($ post_id, $ post) {
        update_post_meta ($ post_id, '_my_metadata', $ _POST ['my_metadata']);
    }
MikeSchinkel
fuente
1

Personalmente, prefiero seguir el siguiente patrón para agregar meta manejadores personalizados a los tipos de publicaciones. Con lo siguiente, puede agregar el meta soporte a un tipo de publicación simplemente agregando la clave de soportes ('subtítulo' en el ejemplo a continuación) a la matriz de soportes para el tipo de publicación llamando a add_post_type_support ('my_post_type', 'subtitle');

class Subtitle_Meta_Handler {
    public function initialize() {
        add_action('add_meta_boxes', array($this, 'add_metabox'), 10, 2);
        add_action('save_post', array($this, 'update'));
    }

    public function add_metabox($post_type, $post)
    {
        if(post_type_supports($post_type, 'subtitle'))
        {
            add_meta_box('subtitle', 'Subtitle', array($this, 'metabox'), $post_type);
        }
    }

    public function metabox($post)
    {
        $subtitle = get_post_meta($post->ID, 'subtitle', true);
        if(!$subtitle)
        {
            $subtitle = '';
        }
        ?>
        <input type="text" style="width: 70%;" value="<?php echo esc_attr($subtitle);?>" name="subtitle" id="subtitle">
        <?php
        wp_nonce_field('update_subtitle', 'subtitle_nonce');
    }

    public function update($post_id)
    {
        if(wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
            return $post_id;
        }
        if(isset($_REQUEST['subtitle_nonce']) && wp_verify_nonce($_REQUEST['subtitle_nonce'], 'update_subtitle')) {
            $subtitle = trim(strip_tags($_REQUEST['subtitle'], '<b><strong><span><a>'));
            if(empty($subtitle)) {
                delete_post_meta($post_id, 'subtitle');
            } else {
                update_post_meta($post_id, 'subtitle', $subtitle);
            }
        }
    }
}
add_action('init', array(new Subtitle_Meta_Handler(), 'initialize'));

Esperemos que algo así pronto se agregue al núcleo.

prettyboymp
fuente
0

Antes de actualizar, verifique si la publicación actual es o no de su tipo de publicación. Eso aseguraría que no lo guarde para todas las publicaciones.

También debe verificar la entrada (que falta en su ejemplo) y, además, tenga en cuenta que solo puede agregar la acción cuando ese tipo de entrada está activo. Si ese es el caso, no necesita verificar ese tipo de publicación más adelante.

Obtener un tipo de publicación: get_post_type()o$post->post_type;

hakre
fuente
0

No puedo hacer que esto funcione, no estoy seguro de qué estoy haciendo mal, pero estoy tratando de usar el enlace post_updated en lugar de save_post, ya que quiero que estos valores se inserten después de que la publicación se haya actualizado para poder recuperar los valores de los otros campos personalizados .

 function update_meta ($ID = false, $post = false) {
  update_post_meta($ID, 'rest_long', 'Test 1');
  update_post_meta($ID, 'rest_lat', 'Test 2');
}

add_action('post_updated', 'update_meta');
jrutter
fuente
No importa, ¡lo descubrí!
jrutter