Champ personnalisé / méta renseigné par liste déroulante des messages existants?

11

(Ma première question WP jamais posée! Soyez doux!)

Je construis un site qui est principalement constitué de pages (c'est-à-dire statiques), en utilisant WP comme CMS. Au bas de plusieurs pages, apparaîtront 1, 2 ou 3 "boîtes promotionnelles" - essentiellement des images de boutons qui renvoient vers d'autres parties du site. Bien que jusqu'à 3 boîtes promotionnelles apparaîtront sur une page donnée, il y aura ~ 30 différentes à choisir.

Lorsque mon client crée une nouvelle page, j'aimerais qu'il puisse choisir des boîtes promotionnelles à partir de quelque chose comme une liste déroulante de toutes les boîtes promotionnelles possibles.

Il me semble que cela devrait fonctionner comme ceci:

  • Créez un type de publication personnalisé appelé "promo-box". (Bien qu'il puisse tout aussi bien être une balise pour des publications régulières.)
  • Utilisez un outil tel que le modèle de champ personnalisé pour créer une liste déroulante sur l'éditeur de page, où les valeurs des options de liste déroulante sont générées dynamiquement à partir de la liste de toutes les publications existantes de la boîte promotionnelle. ( C'est la partie que je ne sais pas faire. )
  • Accédez aux métadonnées résultantes (le numéro de poste est vraiment tout ce dont j'ai besoin, alors je peux obtenir tout le reste) sur le modèle de page.

Sur la base des réponses à d'autres questions ici, j'ai jeté un premier coup d'œil à WPAlchemy MetaBox, Posts-2-Posts et SLT Custom Fields, mais j'avoue que la documentation pour chacun d'eux est légèrement plus geek que moi, donc je n'ai pas fouillé trop profondément.

Conseil? L'un des outils ci-dessus est-il la bonne solution pour moi, et je dois juste le découvrir? Est-ce que j'ai râté quelque chose?

Nic Warmenhoven
la source
Wow, merci pour tout le soutien! J'espère que je ne dévalorise en aucun cas le temps et la générosité de MikeSchinkel, mais j'ai choisi la réponse WPAlchemy comme réponse "officielle". Je suis encore assez nouveau pour PHP / Wordpress que je ne suis pas encore très à l'aise avec les classes et les hooks et les fonctions statiques et autres. J'espère un jour être aussi compétent que vous tous!
Nic Warmenhoven

Réponses:

7

En tant qu'auteur de WPAlchemy , je suis un peu biaisé, mais vous avez essentiellement un bon modèle de travail décrit à suivre en fonction de la route que vous choisissez.

Cependant, si vous utilisez WPAlchemy, vous feriez essentiellement quelque chose comme ceci (étape # 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.csspeut contenir des styles avec lesquels vous pouvez styliser votre formulaire et custom/meta.phpest essentiellement un fichier HTML avec le contenu FORM de la zone de méta, dans ce cas votre liste déroulante, pour générer votre liste déroulante, vous feriez une requête wp personnalisée pour obtenir tous vos messages personnalisés les types. WPAlchemy possède des fonctions d'assistance spéciales pour vous aider à créer vos éléments de formulaire.

Il existe une documentation supplémentaire pour vous aider lorsque vous travaillez dans le modèle.

L'objectif principal de WPAlchemy était de garder le contrôle entre les mains du développeur, du style (look + feel) à la définition du contenu de la meta box.

Et moi-même et les autres sommes toujours prêts à aider ceux qui commentent et posent des questions.

farinspace
la source
1
Bonne réponse, mais puis-je suggérer d'accrocher cette demande de feuille de style supplémentaire spécifiquement à l'écran de rédaction de publication. La même chose peut également être dite pour la création de métabox, qui devrait idéalement être accrochée do_meta_boxesà une logique conditionnelle ou alternativement à add_meta_boxes_{%TYPE%}..
t31os
14

Hehe, tu es un débutant! On va vous déchirer ...!

j / k :) Nous offrons un accueil chaleureux à tous les débutants ici, heureux de vous avoir.

C'est donc la troisième fois que j'entends cette exigence, deux fois de la part des clients et pas encore de vous (et de votre client). Cela me dit que c'est un besoin assez courant.

Metabox personnalisé WordPress affichant trois (3) listes déroulantes

J'ai aimé votre analyse, j'ai donc décidé de coder une classe pour répondre à votre 2e point. Je l'ai appelé LittlePromoBoxesparce que je ne peux jamais sortir cette chanson de ma tête grâce à eux . Fondamentalement, j'utilise la classe pour encapsuler pour éviter autrement les conflits de nommage potentiels avec les fonctions que j'aurais besoin d'écrire.

Vous pouvez mettre cette classe dans le functions.phpfichier de votre thème ou dans le fichier .PHP d'un plugin que vous pourriez écrire (mais ne vous inquiétez pas, cela semble beaucoup plus complexe qu'il ne l'est).

La première fonction on_load()est une fonction statique que j'appelle à la fin de la déclaration de classe pour initialiser les trois (3) hooks dont vous aurez besoin (les fonctions statiques fyi sont essentiellement des fonctions liées à la classe , pas l'instance) :

  1. Le initcrochet pour enregistrer le promo-boxtype de poste,

  2. Le add_meta_boxes_postcrochet pour vous permettre de définir la métabox, et

  3. Le wp_insert_post_datacrochet pour vous permettre de capturer les boîtes promotionnelles sélectionnées et de les enregistrer dans la base de données.

Chacun de ces crochets fait référence à une autre fonction statique de la classe (ce sont les fonctions que j'encapsulais en créant la classe.)

Je vais sauter la description de la action_init()fonction et ma make_labels()fonction d'assistance en supposant que vous savez comment enregistrer un type de message en fonction de votre question.

La action_add_meta_boxes_post()fonction enregistre la métabox à l'aide de la fonction principale de WordPress add_meta_box()et j'ai commenté ses paramètres pour expliquer pourquoi j'ai réussi ce que j'ai réussi pour chacun. La fonction de rappel the_little_promo_boxes_metabox()est bien sûr une autre fonction statique de la classe et c'est ce qui affiche réellement le contenu dans la métabox. Il utilise principalement la fonction principale de WordPress wp_dropdown_pages()pour afficher une liste de boîtes promotionnelles (notez qu'il affichera d'autres types de messages en plus de la page, mais uniquement s'ils sont marqués comme étant 'hierarchical'=>truedans leur enregistrement de type de message. Pourquoi seulement hiérarchiques? Parce que c'est ainsi qu'ils l'a écrit, c'est pourquoi! :)

Puisque nous montrons trois (3) listes déroulantes, nous devons donner à chacun un ID unique dans le HTML ( "promo_box_{$i}") mais le même nom avec des crochets ( 'promo_boxes[]') afin que PHP les recueille dans un tableau à l'intérieur d'une $_POSTvariable (à laquelle WordPress accède pour nous; vous verrez comment dans une minute) . Et bien sûr, nous devons définir la valeur sélectionnée ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])) si en effet l'une des valeurs avait déjà été sélectionnée.

J'ai également utilisé la fonction principale de WordPress get_post_type_object()pour montrer comment obtenir les étiquettes d'un type de publication, et également utiliser la fonction principale de WordPress get_post_meta()pour récupérer un tableau d'ID de boîte promotionnelle à l'aide de la clé de champ personnalisée '_promo_boxes' que je vais vous montrer. pour enregistrer ensuite (notez que j'ai utilisé un soulignement précédent dans le nom, '_promo_boxes'ce qui fait que WordPress se cache de l'interface utilisateur de champ personnalisé standard lorsque l'utilisateur modifie le message.) .

La dernière fonction à décrire avant de voir le code est celle filter_wp_insert_post_data()qui reçoit les données de publication existantes dans le premier paramètre ( $data) et le contenu du $_POSTtableau grâce à WordPress comme deuxième paramètre ( $postarr). À l'intérieur de cette fonction, nous appelons la fonction principale de WordPress update_post_meta()et extrayons le tableau des boîtes promotionnelles ( $postarr['promo_boxes']) pour l'enregistrer dans la valeur de champ personnalisé pour la clé '_promo_boxes'du message spécifié par le $_POSTtableau (c. $postarr['ID']-à-d.).

Cela dit, voici le code de la LittlePromoBoxesclasse:

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();

Il y a encore deux (2) fonctions statiques non encore mentionnées: get_promo_boxes()et get_promo_box(); ce sont des fonctions d'aide pour vous aider à récupérer les messages de post_type='promo-box'par leur nombre ordinal 1..3. Mais pour les rendre plus WordPress comme ici, deux fonctions d'encapsulation sont à ajouter au functions.phpfichier de votre thème (notez que vous pouvez passer une publication en tant que paramètre, mais ce n'est pas obligatoire, sauf si vous utilisez une publication différente de celle 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);
}

Maintenant, vous pouvez appeler l'une ou les deux de ces fonctions dans votre single.phpfichier de thème avec un code qui pourrait ressembler à ceci (ce code aurait pu être écrit en boucle mais la plupart des themers WordPress semblent aimer dupliquer le code afin qu'ils puissent le lire au lieu d'éliminer la redondance Donc, quand à Rome ...):

<?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>';
?>
MikeSchinkel
la source
1
Vous n'arrêtez jamais de m'étonner avec vos réponses, l'effort que vous passez pour créer le code, et expliquer chaque étape .. génial! .. (votre mention de petites cases me fait aussi penser à une de mes séries TV préférées) ..
t31os
1
@ t31os - Merci! Quand je commence à répondre, je ne peux pas m'arrêter. Obsessionnel / compulsif je suppose. Mais au moins je m'en sers bien!
MikeSchinkel
@toscho - Merci. Oui, j'ajoute si rarement de l'humour qu'en ce qui me concerne, je ne peux pas résister. :-)
MikeSchinkel