¿Campo personalizado / meta poblado por el menú desplegable de publicaciones existentes?


11

(¡Mi primera pregunta de WP que se hizo! ¡Sé amable!)

Estoy construyendo un sitio que es principalmente páginas (es decir, estático), usando WP como CMS. En la parte inferior de varias de las páginas, aparecerán 1, 2 o 3 "cuadros de promoción", básicamente imágenes de botones que enlazan con otras partes del sitio. Aunque solo aparecerán hasta 3 cuadros de promoción en cualquier página, habrá ~ 30 diferentes para elegir.

Cuando mi cliente crea una nueva página, me gustaría que pueda elegir cuadros de promoción de algo así como una lista desplegable de todos los cuadros de promoción posibles.

Me parece que esto debería funcionar así:

  • Crea un tipo de mensaje personalizado llamado "cuadro de promoción". (Aunque podría ser fácilmente una etiqueta para publicaciones regulares).
  • Use una herramienta como Plantilla de campo personalizada para crear un menú desplegable en el editor de páginas, donde los valores de las opciones desplegables se generan dinámicamente a partir de la lista de todas las publicaciones de cuadros de promoción existentes. ( Esta es la parte que no sé hacer ) .
  • Acceda a los metadatos resultantes (el número de publicación es realmente todo lo que necesito, luego puedo obtener todo lo demás) en la plantilla de página.

Basado en las respuestas a otras preguntas aquí, he echado un vistazo inicial a los campos personalizados WPAlchemy MetaBox, Posts-2-Posts y SLT, pero confieso que la documentación para cada uno de ellos es un poco más geek de lo que soy, así que no he profundizado Demasiado profundo.

¿Consejo? ¿Es una de las herramientas anteriores la solución adecuada para mí, y solo tengo que resolverlo? ¿Me estoy perdiendo de algo?


¡Guau, gracias por todo el apoyo! Espero no estar devaluando el tiempo y la generosidad de MikeSchinkel, pero elegí la respuesta de WPAlchemy como la respuesta "oficial". Todavía soy lo suficientemente nuevo en PHP / Wordpress que todavía no me siento muy cómodo con las clases y los ganchos y las funciones estáticas y demás. ¡Espero algún día ser tan competente como ustedes!
Nic Warmenhoven

Respuestas:


7

Como autor de WPAlchemy , soy un poco parcial , pero esencialmente tienes un buen modelo de trabajo descrito para seguir dependiendo de la ruta que elijas.

Sin embargo, si usa WPAlchemy, básicamente haría algo como lo siguiente (paso # 2):

//  functions.php

include_once 'WPAlchemy/MetaBox.php';

if (is_admin()) 
{
    // a custom style sheet if you want to do some fancy styling for your form
    wp_enqueue_style('custom_meta_css', TEMPLATEPATH . '/custom/meta.css');
}

// define the meta box
$custom_metabox = new WPAlchemy_MetaBox(array
(
    'id' => '_custom_meta',
    'title' => 'My Custom Meta',
    'template' => TEMPLATEPATH . '/custom/meta.php'
));

custom/meta.csspuede contener estilos con los que puede diseñar su formulario y custom/meta.phpes esencialmente un archivo HTML con el contenido FORM del cuadro meta, en este caso su menú desplegable, para generar su menú desplegable, haría una consulta wp personalizada para obtener toda su publicación personalizada tipos. WPAlchemy tiene algunas funciones auxiliares especiales para ayudarlo a crear sus elementos de formulario.

Hay documentación adicional para ayudarlo cuando trabaja en la plantilla.

El objetivo principal de WPAlchemy era mantener el control en manos del desarrollador, desde el diseño (look + feel) hasta la definición del contenido de meta box.

Y yo y otros siempre estamos dispuestos a ayudar a quienes comentan y hacen preguntas.


1
Buena respuesta, pero puedo sugerir que enganche esa solicitud de hoja de estilo adicional específicamente a la pantalla de edición de publicaciones. Lo mismo también se puede decir para la creación de metabox, que idealmente debería engancharse do_meta_boxescon alguna lógica condicional o, alternativamente, en add_meta_boxes_{%TYPE%}...
t31os

14

Jeje, eres un novato! ¡Te destrozaremos ...!

j / k :) Ofrecemos una cálida bienvenida a todos los novatos aquí, me alegro de tenerte.

Esta es la tercera vez que escucho este requisito, dos veces de clientes y no de usted (y de su cliente). Eso me dice que es una necesidad razonablemente común.

WordPress Metabox personalizado que muestra tres (3) menús desplegables

Me gustó su análisis, así que decidí codificar una clase para abordar su segundo punto. Lo llamé LittlePromoBoxesporque nunca puedo sacar esta canción de mi cabeza, gracias a ellos . Básicamente, uso la clase para encapsular para evitar conflictos de nombres potenciales con las funciones que necesito escribir.

Puede poner esta clase en el functions.phparchivo de su tema o en un archivo .PHP de un complemento que podría estar escribiendo (pero no se preocupe, parece mucho más complejo de lo que es).

La primera función on_load()es una función estática que llamo al final de la declaración de clase para inicializar los tres (3) ganchos que necesitará (sus funciones estáticas son esencialmente funciones relacionadas con la clase , no con la instancia) :

  1. El initgancho para registrar el promo-boxtipo de publicación,

  2. El add_meta_boxes_postgancho para permitirle definir el metabox, y

  3. El wp_insert_post_datagancho para permitirle capturar los cuadros de promoción seleccionados y guardarlos en la base de datos.

Cada uno de esos ganchos hace referencia a otra función estática en la clase (estas fueron las funciones que estaba encapsulando al crear la clase).

Me saltearé la descripción de la action_init()función y mi make_labels()función auxiliar, suponiendo que sepa cómo registrar un tipo de publicación en función de su pregunta.

La action_add_meta_boxes_post()función registra el metabox usando la función principal de WordPress add_meta_box()y he comentado sus parámetros para explicar por qué pasé lo que pasé por cada uno. La función de devolución de llamada the_little_promo_boxes_metabox()es, por supuesto, otra función estática de la clase y es lo que realmente muestra el contenido en el metabox. Utiliza principalmente la función principal de WordPress wp_dropdown_pages()para mostrar una lista de cuadros de promoción (tenga en cuenta que mostrará otros tipos de publicaciones además de 'página' pero solo si están marcadas como 'hierarchical'=>trueen su registro de tipo de publicación. ¿Por qué solo jerárquico? Porque esa es la forma en que lo escribió, por eso! :)

Como estamos mostrando tres (3) menús desplegables, debemos dar a cada uno un ID único en HTML ( "promo_box_{$i}") pero el mismo nombre con corchetes ( 'promo_boxes[]') para que PHP los recopile en una matriz dentro de la $_POSTvariable (a la que WordPress accede por nosotros; Verás cómo en un minuto) . Y, por supuesto, necesitamos establecer el valor seleccionado ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])) si de hecho uno de los valores se había seleccionado previamente.

También utilicé la función principal de WordPress get_post_type_object()para mostrar cómo obtener las etiquetas de un tipo de publicación, y también utilicé la función principal de WordPress get_post_meta()para recuperar una variedad de ID de cuadros de promoción usando la tecla de campo personalizada '_promo_boxes' que mostraré que tiene para guardar el siguiente (tenga en cuenta que utilicé un guión bajo anterior en el nombre '_promo_boxes'que hace que WordPress se oculte de la interfaz de usuario de campo personalizado estándar cuando el usuario está editando la publicación) .

La última función para describir antes de ver el código es la filter_wp_insert_post_data()que recibe los datos de publicación existentes en el primer parámetro ( $data) y el contenido de la $_POSTmatriz gracias a WordPress como el segundo parámetro ( $postarr). Dentro de esta función, llamamos a la función principal de WordPress update_post_meta()y extraemos la matriz de cuadros de promoción ( $postarr['promo_boxes']) para guardar en el valor del campo personalizado para la clave '_promo_boxes'de la publicación especificada por la $_POSTmatriz (es decir $postarr['ID']).

Dicho esto, aquí está el código para la LittlePromoBoxesclase:

class LittlePromoBoxes {
  static function on_load() {
    add_action('init',array(__CLASS__,'action_init'));
    add_action('add_meta_boxes_post',array(__CLASS__,'action_add_meta_boxes_post'));
    add_filter('wp_insert_post_data',array(__CLASS__,'filter_wp_insert_post_data'),10,2);
  }
  static function action_init() {
    register_post_type('promo-box',array(
      'labels'          => self::make_labels('Promo Box','Promo Boxes'),
      'public_queryable'=> false,
      'hierarchical'    => true,  // IMPORTANT!!! wp_dropdown_pages() requires 'hierarchical'=>true
      'show_ui'         => true,
      'query_var'       => false,
      'supports'        => array('title','editor','thumbnail','custom-fields'),
      'show_in_nav_menus'=>true,
      'exclude_from_search'=>true,
    ));
  }
  static function make_labels($singular,$plural=false,$args=array()) {
    if ($plural===false)
      $plural = $singular . 's';
    elseif ($plural===true)
      $plural = $singular;
    $defaults = array(
      'name'              =>_x($plural,'post type general name'),
      'singular_name'      =>_x($singular,'post type singular name'),
      'add_new'            =>_x('Add New',$singular),
      'add_new_item'      =>__("Add New $singular"),
      'edit_item'          =>__("Edit $singular"),
      'new_item'          =>__("New $singular"),
      'view_item'          =>__("View $singular"),
      'search_items'      =>__("Search $plural"),
      'not_found'          =>__("No $plural Found"),
      'not_found_in_trash'=>__("No $plural Found in Trash"),
      'parent_item_colon' =>'',
    );
    return wp_parse_args($args,$defaults);
  }
  static function action_add_meta_boxes_post($post) {
    add_meta_box(
      'little-promo-boxes',   // Metabox Name, used as the "id" for a wrapping div
      'Little Promo Boxes',   // Metabox Title, visible to the user
      array(__CLASS__,'the_little_promo_boxes_metabox'), // Callback function
      'post',                 // Add to the Edit screen for Post Types of 'post'  
      'side',                 // Show it in the sidebar (if center then it would be 'normal'
      'low'                   // Show it below metaboxes that specify 'high'
    );
  }
  static function the_little_promo_boxes_metabox($post) {
    $pto = get_post_type_object('promo-box');
    $default_options = array(
      'post_type' => 'promo-box',
      'show_option_none' => "Select a {$pto->labels->singular_name}",
    );
    $promo_boxes = get_post_meta($post->ID,'_promo_boxes',true);
    for($i=0; $i<=2; $i++) {
      wp_dropdown_pages(array_merge($default_options,array(
        'id'       => "promo_box_{$i}",
        'name'     => 'promo_boxes[]',
        'selected' => (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i]),
      )));
    }
  }
  static function filter_wp_insert_post_data($data, $postarr) {
    update_post_meta($postarr['ID'],'_promo_boxes',$postarr['promo_boxes']);
    return $data;
  }
  static function get_promo_boxes($post=false) {
    static $promo_boxes=array();
    if (!$post)
      $post = $GLOBALS['post'];
    if (!isset($promo_boxes[$post->ID])) {
      $promo_boxes[$post->ID] = get_post_meta($post->ID,'_promo_boxes',true);
      $index = 0;
      foreach($promo_boxes[$post->ID] as $promo_box_id) {
        $promo_boxes[$post->ID][$index++] = (is_numeric($promo_box_id) ? get_post($promo_box_id) : false);
      }
    }
    return $promo_boxes[$post->ID];
  }
  static function get_promo_box($number,$post=false) {
    $promo_boxes = self::get_promo_boxes($post);
    return $promo_boxes[$number-1];
  }
}
LittlePromoBoxes::on_load();

Todavía hay dos (2) funciones estáticas aún no mencionadas: get_promo_boxes()y get_promo_box(); Estas son funciones de ayuda para ayudarlo a recuperar las publicaciones post_type='promo-box'por sus números ordinales 1..3. Pero para hacerlos más WordPress como aquí hay dos funciones de contenedor para agregar al functions.phparchivo de su tema (tenga en cuenta que puede pasar una publicación como parámetro pero no tiene que hacerlo a menos que esté utilizando una publicación diferente a la de The Loop ) :

function get_little_promo_boxes($post=false) {
  return LittlePromoBoxes::get_promo_boxes($post);
}
function get_little_promo_box($number,$post=false) {
  return LittlePromoBoxes::get_promo_box($number,$post);
}

Ahora puede llamar a una o ambas funciones en su single.phparchivo de tema con un código que podría verse así (este código podría haberse escrito en un bucle, pero a la mayoría de los temáticos de WordPress parece que les gusta duplicar el código para que puedan leerlo en lugar de eliminar la redundancia Entonces, cuando en Roma ...):

<?php
  $promo_boxes = get_little_promo_boxes();
  if (isset($promo_boxes[1]))
    echo '<div id="promo-box1" class="promo-box">' . get_the_title($promo_boxes[1]->ID) . '</div>';
  if (isset($promo_boxes[2]))
    echo '<div id="promo-box2" class="promo-box">' . get_the_title($promo_boxes[2]->ID) . '</div>';
  if (isset($promo_boxes[3]))
    echo '<div id="promo-box3" class="promo-box">' . get_the_title($promo_boxes[3]->ID) . '</div>';
?>

1
Nunca dejas de sorprenderme con tus respuestas, el esfuerzo que haces para crear el código y explicar cada paso ... ¡increíble! ... (tu mención de pequeñas cajas también me hace pensar en una de mis series de TV favoritas) ...
t31os

1
@ t31os - ¡Gracias! Cuando empiezo a contestar simplemente no puedo detenerme. Obsesivo / compulsivo, supongo. ¡Pero al menos estoy haciendo buen uso!
MikeSchinkel

@toscho - Gracias. Sí, rara vez agrego humor que cuando se trata de mí no puedo resistirme. :-)
MikeSchinkel
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.