Campo personalizzato / meta popolato dal menu a discesa dei post esistenti?


11

(La mia prima domanda sul WP mai fatta! Sii gentile!)

Sto costruendo un sito che è principalmente pagine (cioè statiche), usando WP come CMS. Nella parte inferiore di diverse pagine, appariranno 1, 2 o 3 "riquadri promozionali", sostanzialmente immagini di pulsanti che rimandano ad altre parti del sito. Anche se in ogni pagina appariranno solo fino a 3 scatole promozionali, ce ne saranno circa 30 diverse tra cui scegliere.

Quando il mio cliente crea una nuova pagina, mi piacerebbe che potesse scegliere le scatole promozionali da qualcosa come un elenco a discesa di tutte le possibili scatole promozionali.

Mi sembra che dovrebbe funzionare così:

  • Crea un tipo di post personalizzato chiamato "promo-box". (Anche se potrebbe essere altrettanto facilmente un tag per post regolari.)
  • Utilizzare uno strumento come Modello campo personalizzato per creare un menu a discesa nell'editor di pagine, in cui i valori delle opzioni a discesa sono generati dinamicamente dall'elenco di tutti i post della casella promozionale esistenti. ( Questa è la parte che non so fare. )
  • Accedi ai metadati risultanti (il numero di post è davvero tutto ciò di cui ho bisogno, quindi posso ottenere tutto il resto) sul modello di pagina.

Sulla base delle risposte ad altre domande qui, ho dato uno sguardo iniziale a WPAlchemy MetaBox, Posts-2-Posts e SLT Custom Fields, ma confesso che la documentazione per ognuno di essi è leggermente più geek di me, quindi non ho approfondito troppo profondamente.

Consigli? Uno degli strumenti di cui sopra è la soluzione giusta per me e devo solo capirlo? Mi sto perdendo qualcosa qui?


Wow, grazie per tutto il supporto! Spero di non svalutare in alcun modo il tempo e la generosità di MikeSchinkel, ma ho scelto la risposta WPAlchemy come risposta "ufficiale". Sono ancora abbastanza nuovo per PHP / Wordpress che non mi sento ancora a mio agio con classi, hook e funzioni statiche e simili. Spero un giorno di essere bravo quanto tutti voi!
Nic Warmenhoven,

Risposte:


7

Come autore di WPAlchemy , sono un po ' distorto , ma essenzialmente hai un buon modello di lavoro delineato da seguire a seconda di quale percorso sceglierai.

Tuttavia, se usi WPAlchemy, dovresti sostanzialmente fare qualcosa del tipo seguente (passaggio 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.csspuò contenere stili con cui puoi modellare il tuo modulo ed custom/meta.phpè essenzialmente un file HTML con i contenuti FORM del meta-box, in questo caso il tuo menu a discesa, per generare il tuo menu a discesa faresti una query wp personalizzata per ottenere tutto il tuo post personalizzato tipi. WPAlchemy ha alcune funzioni speciali di aiuto per aiutarti a creare gli elementi del tuo modulo.

È disponibile una documentazione aggiuntiva per assistere l'utente quando si lavora nel modello.

L'obiettivo principale di WPAlchemy era mantenere il controllo nelle mani dello sviluppatore, dallo stile (look + feel) alla definizione del contenuto dei meta-box.

E io e gli altri siamo sempre disposti ad aiutare coloro che commentano e fanno domande.


1
Bella risposta, ma potrei suggerire di associare quella richiesta di foglio di stile in più alla schermata di post-editing. Lo stesso si può dire anche per la creazione di metabox, che idealmente dovrebbe essere agganciato do_meta_boxescon una logica condizionale o in alternativa su add_meta_boxes_{%TYPE%}...
t31os

14

Hehe, sei un principiante! Ti faremo a brandelli ...!

j / k :) Offriamo un caloroso benvenuto a tutti i principianti qui, felice di averti.

Quindi questa è la terza volta che ho sentito questo requisito, due volte dai clienti e non ancora da te (e dal tuo cliente). Questo mi dice che è un'esigenza ragionevolmente comune.

Metabox personalizzato di WordPress che mostra tre (3) menu a discesa

Mi è piaciuta la tua analisi, quindi ho deciso di codificare una classe per affrontare il tuo secondo punto. L'ho chiamato LittlePromoBoxesperché non riesco mai a togliermi dalla testa questa canzone , grazie a loro . Fondamentalmente uso la classe per incapsulare per evitare potenziali conflitti di denominazione con le funzioni che avrei bisogno di scrivere.

Puoi inserire questa classe nel functions.phpfile del tuo tema o in un file .PHP di un plugin che potresti scrivere (ma non preoccuparti, sembra molto più complesso di quanto non sia.)

La prima funzione on_load()è una funzione statica che chiamo alla fine della dichiarazione di classe per inizializzare i tre (3) hook necessari (le funzioni statiche sono essenzialmente funzioni correlate alla classe , non all'istanza) :

  1. L' inithook per registrare il promo-boxtipo di post,

  2. Il add_meta_boxes_postgancio per consentire di definire il metabox e

  3. Il wp_insert_post_datagancio per consentire di acquisire le scatole promozionali selezionate e salvarle nel database.

Ognuno di questi hook fa riferimento a un'altra funzione statica nella classe (queste erano le funzioni che stavo incapsulando creando la classe).

Salterò descrivendo la action_init()funzione e la mia make_labels()funzione di supporto supponendo che tu sappia come registrare un tipo di post in base alla tua domanda.

La action_add_meta_boxes_post()funzione registra il metabox usando la funzione principale di WordPress add_meta_box()e ho commentato i suoi parametri per spiegare perché ho passato quello che ho passato per ciascuno. La funzione di callback the_little_promo_boxes_metabox()è ovviamente un'altra funzione statica della classe ed è ciò che effettivamente visualizza il contenuto nel metabox. Utilizza principalmente la funzione principale di WordPress wp_dropdown_pages()per visualizzare un elenco di riquadri promozionali ( tieni presente che visualizzerà altri tipi di post oltre a "pagina" ma solo se sono contrassegnati come registrati 'hierarchical'=>truenella loro registrazione del tipo di post. Perché solo gerarchici? Perché è così che l'ho scritto, ecco perché! :)

Dato che stiamo mostrando tre (3) menu a discesa, dobbiamo dare a ciascuno un ID univoco in HTML ( "promo_box_{$i}") ma lo stesso nome con parentesi quadre ( 'promo_boxes[]') in modo che PHP li raccolga in un array all'interno di una $_POSTvariabile (a cui WordPress accede per noi; vedrai come tra un minuto) . E ovviamente dobbiamo impostare il valore selezionato ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])) se effettivamente uno dei valori fosse stato precedentemente selezionato.

Ho anche usato la funzione principale di WordPress get_post_type_object()per mostrare come ottenere le etichette da un tipo di post e anche usare la funzione principale di WordPress get_post_meta()per recuperare una matrice di ID casella promozionale dall'uso del tasto campo personalizzato '_promo_boxes' che ti mostrerò per salvare il prossimo (nota che ho usato un carattere di sottolineatura precedente nel nome '_promo_boxes'che fa sì che WordPress si nasconda dall'interfaccia utente del campo personalizzato standard quando l'utente sta modificando il post.) .

L'ultima funzione da descrivere prima di vedere il codice è quella filter_wp_insert_post_data()che riceve i dati di posta esistenti nel primo parametro ( $data) e il contenuto $_POSTdell'array grazie a WordPress come secondo parametro ( $postarr). All'interno di questa funzione chiamiamo la funzione principale di WordPress update_post_meta()ed estraiamo l'array di scatole promozionali ( $postarr['promo_boxes']) per salvare nel valore di campo personalizzato per la chiave '_promo_boxes'per il post specificato $_POSTdall'array (cioè $postarr['ID']).

Detto questo, ecco il codice per 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();

Esistono ancora due (2) funzioni statiche non ancora menzionate: get_promo_boxes()e get_promo_box(); queste sono funzioni di aiuto per aiutarti a recuperare i messaggi post_type='promo-box'dai loro numeri ordinali 1..3. Ma per renderli più WordPress come qui ci sono due funzioni wrapper da aggiungere al functions.phpfile del tuo tema (nota che puoi passare un post come parametro ma non devi farlo a meno che tu non stia usando un post diverso da quello in 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);
}

Ora puoi chiamare una o entrambe queste funzioni nel tuo single.phpfile del tema con un codice che potrebbe assomigliare a questo (questo codice potrebbe essere stato scritto in un ciclo ma la maggior parte dei temi di WordPress sembra voler duplicare il codice in modo da poterlo leggere invece di eliminare la ridondanza Quindi, quando a 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
Non smetti mai di stupirmi con le tue risposte, lo sforzo che fai per creare il codice e spiegare ogni passaggio .. fantastico! .. (la tua menzione di piccole scatole mi fa pensare anche a una delle mie serie TV preferite) ..
t31os,

1
@ t31os - Grazie! Quando inizio a rispondere non riesco proprio a smettere. Credo che sia ossessivo / compulsivo. Ma almeno sto facendo buon uso!
MikeSchinkel,

@toscho - Grazie. Sì, aggiungo così raramente umorismo che quando si tratta di me non posso resistere. :-)
MikeSchinkel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.