web-dev-qa-db-fra.com

Champ personnalisé/méta renseigné par liste déroulante des publications existantes?

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

Je construis un site composé principalement de pages (c'est-à-dire, statiques), en utilisant WP comme système de gestion de contenu. Au bas de plusieurs pages, apparaissent 1, 2 ou 3 "boîtes de promotion" - essentiellement des images de boutons qui renvoient vers d'autres parties du site. Bien que seules 3 boîtes promotionnelles apparaissent sur une page donnée, il en existe environ 30 différentes.

Lorsque mon client crée une nouvelle page, j'aimerais qu'il puisse choisir des boîtes de promotions dans une liste déroulante de toutes les boîtes de promotions possibles.

Il me semble que cela devrait fonctionner comme ceci:

  • Créez un type de message personnalisé appelé "boîte de promotion". (Bien que cela puisse tout aussi bien être un tag pour les posts réguliers.)
  • Utilisez un outil tel que Modèle de champ personnalisé pour créer une liste déroulante dans l'éditeur de page, dans laquelle les valeurs des options de liste déroulante sont générées de manière dynamique à partir de la liste de tous les articles de la boîte de promotion existants. (C'est la partie que je ne sais pas faire.)
  • Accédez aux métadonnées résultantes (le numéro de message est 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 aux autres questions ici, j’ai jeté un coup d’œil initial à WPAlchemy MetaBox, Posts-2-Posts et SLT Custom Fields, mais j’avoue que la documentation de chacune d’elles est légèrement plus geek que moi, c’est pourquoi je n’ai pas fouillé. trop profondément.

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

11
Nic Warmenhoven

En tant que auteur de WPAlchemy , je suis un peu partial, mais vous avez essentiellement un bon modèle de travail à 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.css peut contenir des styles avec lesquels vous pouvez styler votre formulaire et custom/meta.php est essentiellement un fichier HTML avec le contenu du formulaire de la méta-boîte. Dans ce cas, votre liste déroulante génère une liste déroulante. types de messages personnalisés. WPAlchemy propose des fonctions d'assistance spéciales pour vous aider à créer vos éléments de formulaire.

Il existe des documentation supplémentaires 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 boîte méta.

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

7
farinspace

_ {Hé, vous êtes un débutant! Nous allons vous déchirer en lambeaux ...!} _

j/k :) Nous souhaitons la bienvenue à tous les débutants, ravis de vous accueillir.

C’est donc la troisième fois que j’entends parler de cette exigence, deux fois de la part de clients et non plus de votre part (et de votre client). Cela me dit que c’est un besoin assez courant.

WordPress Custom Metabox showing Three (3) Dropdowns

J'ai aimé votre analyse et j'ai donc décidé de coder une classe pour aborder votre deuxième point. Je l'ai appelée LittlePromoBoxes parce que je ne peux jamais obtenir cette chanson de ma tête, grâce à eux . Fondamentalement, j'utilise la classe pour encapsuler afin d'éviter autrement des conflits de noms avec les fonctions que j'aurais besoin d'écrire.

Vous pouvez mettre cette classe dans le fichier functions.php de votre thème ou dans le fichier .PHP d'un plugin que vous écrivez peut-être (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) points d’accrochage dont vous aurez besoin (les fonctions statiques fyi sont essentiellement fonctions liées à la classe , pas l'instance):

  1. Le hook init pour enregistrer le type d'article promo-box,

  2. Le crochet add_meta_boxes_post pour vous permettre de définir la metabox, et

  3. Le crochet wp_insert_post_data vous permet de capturer les boîtes de promotions sélectionnées et de les enregistrer dans la base de données.

Chacun de ces hooks fait référence à une autre fonction statique de la classe (c’étaient les fonctions que j’encapsulais en créant la classe.)}

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

La fonction action_add_meta_boxes_post() enregistre la metabox à l’aide de la fonction principale WordPress add_meta_box() et j’ai commenté ses paramètres pour expliquer pourquoi j’ai passé ce que j’ai passé 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 metabox. Il utilise principalement la fonction principale wp_dropdown_pages() de WordPress pour afficher une liste de boîtes de promotion (notez qu'il affichera d'autres types de publication en plus de 'page', mais uniquement si elles sont marquées comme étant 'hierarchical'=>true dans leur enregistrement de type de publication. Pourquoi uniquement une hiérarchie? Parce que c'est comme ça qu'ils l'ont écrit, c'est pour ça! :)

Puisque nous affichons trois (3) menus déroulants, nous devons attribuer à chacun un identifiant unique dans le code HTML ("promo_box_{$i}"), mais le même nom avec des crochets ('promo_boxes[]') afin que PHP les rassemble dans un tableau à l'intérieur. $_POST variable (auquel WordPress a accès 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 effectivement l'une des valeurs avait déjà été sélectionnée.

J'ai également utilisé la fonction de base WordPress get_post_type_object() pour montrer comment obtenir les libellés d'un type de publication, ainsi que la fonction de base WordPress get_post_meta() pour récupérer un tableau d'ID de boîtes promotionnelles à l'aide de la clé de champ personnalisée '_promo_boxes' que je montrerai. vous devez enregistrer le suivant (remarque: j’ai utilisé le caractère de soulignement précédent dans le nom '_promo_boxes', ce qui a pour effet de masquer WordPress de l’interface utilisateur des champs personnalisés standard lorsque l’utilisateur modifie le message.).

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

Cela dit, voici le code de la classe LittlePromoBoxes:

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 auxiliaires qui vous aident à récupérer les publications de post_type='promo-box' par leurs nombres ordinaux 1..3. Mais pour les rendre plus WordPress, voici deux fonctions d’emballage à ajouter au fichier functions.php de votre thème (notez que vous pouvez passer un message en tant que paramètre, mais vous n’êtes pas obligé de le faire, sauf si vous utilisez un autre message que celui dans la boucle ):

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

Vous pouvez maintenant appeler une ou les deux fonctions de votre fichier de thème single.php avec un code qui pourrait ressembler à ceci: (ce code aurait pu être écrit en boucle, mais la plupart des utilisateurs de WordPress semblent aimer dupliquer le code afin de 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>';
?>
14
MikeSchinkel