Benutzerdefiniertes Feld / Meta, das durch Dropdown vorhandener Beiträge gefüllt wird?

11

(Meine erste WP-Frage, die jemals gestellt wurde! Sei sanft!)

Ich erstelle eine Site, die hauptsächlich aus Seiten besteht (dh statisch), und verwende WP als CMS. Am Ende mehrerer Seiten werden 1, 2 oder 3 "Promo-Boxen" angezeigt - im Grunde Schaltflächenbilder, die auf andere Teile der Website verweisen. Obwohl auf einer bestimmten Seite nur bis zu 3 Promo-Boxen angezeigt werden, stehen ~ 30 verschiedene zur Auswahl.

Wenn mein Kunde eine neue Seite erstellt, möchte ich, dass er Promo-Boxen aus einer Dropdown-Liste aller möglichen Promo-Boxen auswählen kann.

Mir scheint, das sollte so funktionieren:

  • Erstellen Sie einen benutzerdefinierten Beitragstyp mit dem Namen "Promo-Box". (Obwohl es genauso gut ein Tag für reguläre Posts sein könnte.)
  • Verwenden Sie ein Tool wie die benutzerdefinierte Feldvorlage, um ein Dropdown-Menü im Seiteneditor zu erstellen, in dem die Werte der Dropdown-Optionen dynamisch aus der Liste aller vorhandenen Promo-Box-Beiträge generiert werden. ( Dies ist der Teil, den ich nicht weiß. )
  • Greifen Sie auf die resultierenden Metadaten (Post-Nummer ist wirklich alles, was ich brauche, dann kann ich alles andere bekommen) auf der Seitenvorlage zu.

Basierend auf den Antworten auf andere Fragen hier habe ich einen ersten Blick auf die benutzerdefinierten Felder WPAlchemy MetaBox, Posts-2-Posts und SLT geworfen, aber ich gebe zu, dass die Dokumentation für jedes dieser Felder etwas geekiger ist als ich, daher habe ich mich nicht damit befasst zu tief.

Rat? Ist eines der oben genannten Tools die richtige Lösung für mich und ich muss es nur herausfinden? Vermisse ich hier etwas?

Nic Warmenhoven
quelle
Wow, danke für die Unterstützung! Ich hoffe, dass ich MikeSchinkels Zeit und Großzügigkeit sowieso nicht abwerte, aber ich habe die WPAlchemy-Antwort als "offizielle" Antwort gewählt. Ich bin noch neu genug in PHP / Wordpress, dass ich mit Klassen und Hooks und statischen Funktionen und dergleichen noch nicht besonders vertraut bin. Ich hoffe, eines Tages so kompetent zu sein wie Sie alle!
Nic Warmenhoven

Antworten:

7

Als Autor von WPAlchemy bin ich ein bisschen voreingenommen , aber Sie haben im Wesentlichen ein gutes Arbeitsmodell, dem Sie folgen können, je nachdem, welche Route Sie wählen.

Wenn Sie jedoch WPAlchemy verwenden, würden Sie im Grunde Folgendes tun (Schritt 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.csskann Stile enthalten, mit denen Sie Ihr Formular formatieren können, und custom/meta.phpist im Wesentlichen eine HTML-Datei mit dem FORMULAR-Inhalt des Meta-Felds, in diesem Fall Ihrem Dropdown-Menü. Um Ihr Dropdown-Menü zu generieren, führen Sie eine benutzerdefinierte WP-Abfrage durch, um alle Ihre benutzerdefinierten Beiträge abzurufen Typen. WPAlchemy verfügt über einige spezielle Hilfsfunktionen, die Sie beim Erstellen Ihrer Formularelemente unterstützen.

Es gibt zusätzliche Dokumentationen , die Sie bei der Arbeit an der Vorlage unterstützen.

Das Hauptziel von WPAlchemy war es, die Kontrolle in den Händen des Entwicklers zu behalten, vom Styling (Look + Feel) bis zur Definition des Meta-Box-Inhalts.

Und ich und andere sind immer bereit, denen zu helfen, die Kommentare abgeben und Fragen stellen.

Farinspace
quelle
1
Nette Antwort, aber darf ich vorschlagen, diese zusätzliche Stylesheet-Anfrage speziell an den Post-Editoring-Bildschirm anzuschließen. Gleiches gilt auch für die Erstellung von Metaboxen, die idealerweise do_meta_boxesmit einer bedingten Logik oder alternativ mit add_meta_boxes_{%TYPE%}..
t31os
14

Hehe, du bist ein Neuling! Wir werden dich in Stücke reißen ...!

j / k :) Wir heißen alle Neulinge hier herzlich willkommen und freuen uns, Sie zu haben.

Dies ist das dritte Mal, dass ich diese Anforderung zweimal von Kunden und nicht noch einmal von Ihnen (und Ihrem Kunden) gehört habe. Das sagt mir, dass dies ein einigermaßen häufiger Bedarf ist.

WordPress Custom Metabox mit drei (3) Dropdowns

Ihre Analyse hat mir gefallen, deshalb habe ich beschlossen, eine Klasse zu codieren, um Ihren zweiten Punkt anzusprechen. Ich habe es genannt, LittlePromoBoxesweil ich dieses Lied dank ihnen nie aus meinem Kopf bekommen kann . Grundsätzlich verwende ich die Klasse zum Einkapseln, um ansonsten mögliche Namenskonflikte mit den Funktionen zu vermeiden, die ich schreiben müsste.

Sie können diese Klasse in die functions.phpDatei Ihres Themas oder in eine PHP-Datei eines Plugins einfügen, das Sie möglicherweise schreiben (aber keine Sorge, sie sieht viel komplexer aus als sie ist).

Die erste Funktion on_load()ist eine statische Funktion, die ich am Ende der Klassendeklaration aufrufe, um die drei (3) Hooks zu initialisieren, die Sie benötigen (statische Funktionen sind im Wesentlichen Funktionen, die sich auf die Klasse beziehen , nicht auf die Instanz) :

  1. Der initHaken zum Registrieren des promo-boxBeitragstyps,

  2. Der add_meta_boxes_postHook, mit dem Sie die Metabox definieren können, und

  3. Der wp_insert_post_dataHook, mit dem Sie die ausgewählten Promo-Boxen erfassen und in der Datenbank speichern können.

Jeder dieser Hooks verweist auf eine andere statische Funktion in der Klasse (dies waren die Funktionen, die ich durch Erstellen der Klasse gekapselt habe.)

Ich überspringe die Beschreibung der action_init()Funktion und meiner make_labels()Hilfsfunktion, vorausgesetzt, Sie wissen, wie Sie einen Beitragstyp basierend auf Ihrer Frage registrieren.

Die action_add_meta_boxes_post()Funktion registriert die Metabox mithilfe der WordPress-Kernfunktion add_meta_box()und ich habe ihre Parameter kommentiert, um zu erklären, warum ich das übergeben habe, was ich für jedes übergeben habe. Die Rückruffunktion the_little_promo_boxes_metabox()ist natürlich eine weitere statische Funktion der Klasse und zeigt tatsächlich den Inhalt in der Metabox an. Es verwendet hauptsächlich die WordPress-Kernfunktion wp_dropdown_pages(), um eine Liste von Promo-Boxen anzuzeigen (beachten Sie, dass neben "Seite" auch andere Beitragstypen angezeigt werden, jedoch nur, wenn diese 'hierarchical'=>truein ihrer Beitragstypregistrierung markiert sind . Warum nur hierarchisch? Weil sie so sind schrieb es, deshalb! :)

Da wir drei (3) Dropdowns anzeigen, müssen wir jedem eine eindeutige ID im HTML ( "promo_box_{$i}"), aber denselben Namen mit eckigen Klammern ( 'promo_boxes[]') geben, damit PHP sie in einem Array innerhalb der $_POSTVariablen sammelt (auf die WordPress für uns zugreift; Sie werden sehen, wie in einer Minute) . Und natürlich müssen wir den ausgewählten Wert ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])) festlegen, wenn tatsächlich einer der Werte zuvor ausgewählt wurde.

Ich habe auch die WordPress-Kernfunktion verwendet, um get_post_type_object()zu zeigen, wie die Beschriftungen von einem Beitragstyp get_post_meta()abgerufen werden , und auch die WordPress-Kernfunktion , um ein Array von Promo-Box-IDs mithilfe des benutzerdefinierten Feldschlüssels '_promo_boxes' abzurufen, den ich Ihnen zeigen werde neben speichern (Anmerkung benutzte ich einen vorhergehenden Unterstrich im Namen , '_promo_boxes'die Wordpress zu verstecken aus dem Standard - benutzerdefinierten Feld UI verursacht , wenn der Benutzer die Post bearbeitet.) .

Die letzte Funktion, die beschrieben werden muss, bevor Sie den Code sehen, ist filter_wp_insert_post_data()die, die die vorhandenen Post-Daten im ersten Parameter ( $data) und den Inhalt des $_POSTArrays dank WordPress als zweitem Parameter ( $postarr) empfängt . Innerhalb dieser Funktion rufen wir die WordPress-Kernfunktion auf update_post_meta()und extrahieren das Promo-Box-Array ( $postarr['promo_boxes']), um es im benutzerdefinierten Feldwert für den Schlüssel '_promo_boxes'für den vom $_POSTArray angegebenen Beitrag (dh $postarr['ID']) zu speichern .

Das heißt, hier ist der Code für die LittlePromoBoxesKlasse:

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

Es gibt noch zwei (2) statische Funktionen, die noch nicht erwähnt wurden: get_promo_boxes()und get_promo_box(); Dies sind Hilfsfunktionen, mit denen Sie die Beiträge post_type='promo-box'anhand ihrer Ordnungszahlen 1..3 abrufen können. Um sie noch WordPress zu machen, wie hier, müssen Sie zwei Wrapper-Funktionen zur functions.phpDatei Ihres Themas hinzufügen (beachten Sie, dass Sie einen Beitrag als Parameter übergeben können, dies jedoch nicht müssen, es sei denn, Sie verwenden einen anderen Beitrag als den 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);
}

Jetzt können Sie eine oder beide dieser Funktionen in Ihrer Themendateisingle.php mit Code aufrufen , der möglicherweise so aussieht (dieser Code könnte in einer Schleife geschrieben worden sein, aber die meisten WordPress-Themen scheinen gerne Code zu duplizieren, damit sie ihn lesen können, anstatt Redundanz zu beseitigen Also, wenn in Rom ...):

<?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
quelle
1
Sie überraschen mich immer wieder mit Ihren Antworten, dem Aufwand, den Code zu erstellen und jeden Schritt zu erklären. Großartig! (Ihre Erwähnung von kleinen Kästchen lässt mich auch an eine meiner Lieblingsserien denken.)
t31os
1
@ t31os - Danke! Wenn ich anfange zu antworten, kann ich mich einfach nicht aufhalten. Obsessiv / zwanghaft, denke ich. Aber zumindest nutze ich es gut!
MikeSchinkel
@toscho - Danke. Ja, ich füge so selten Humor hinzu, dass ich nicht widerstehen kann, wenn es um mich geht. :-)
MikeSchinkel