Bidang / meta khusus yang diisi oleh dropdown dari posting yang ada?

11

(Pertanyaan WP pertama saya pernah diajukan! Lembut!)

Saya sedang membangun situs yang sebagian besar adalah halaman (yaitu statis), menggunakan WP sebagai CMS. Di bagian bawah beberapa halaman, akan muncul 1, 2, atau 3 "kotak promo" - pada dasarnya gambar-tombol yang menghubungkan ke bagian lain dari situs. Meskipun hanya hingga 3 kotak promo akan muncul pada halaman tertentu, akan ada ~ 30 yang berbeda untuk dipilih.

Ketika klien saya membuat halaman baru, saya ingin dia dapat memilih kotak promo dari sesuatu seperti daftar dropdown dari semua kotak promo yang mungkin.

Menurut saya ini seharusnya bekerja seperti ini:

  • Buat jenis posting khusus yang disebut "kotak promo". (Meskipun bisa dengan mudah menjadi tag untuk posting biasa.)
  • Gunakan alat seperti Template Bidang Kustom untuk membuat dropdown pada editor halaman, di mana nilai opsi dropdown dihasilkan secara dinamis dari daftar semua posting kotak promo yang ada. ( Ini adalah bagian yang saya tidak tahu bagaimana melakukannya. )
  • Akses metadata yang dihasilkan (nomor posting benar-benar yang saya butuhkan, maka saya bisa mendapatkan yang lain) pada templat halaman.

Berdasarkan tanggapan terhadap pertanyaan lain di sini, saya telah melihat WPAlchemy MetaBox, Posts-2-Post, dan SLT Custom Fields, tetapi saya akui dokumentasi untuk masing-masingnya sedikit lebih geekier daripada saya, jadi saya belum menggali terlalu dalam.

Nasihat? Apakah salah satu alat di atas solusi yang tepat untuk saya, dan saya hanya harus mencari tahu? Apakah saya melewatkan sesuatu di sini?

Nic Warmenhoven
sumber
Wow, terima kasih atas semua dukungannya! Saya berharap bahwa saya tidak akan merendahkan waktu dan kemurahan hati MikeSchinkel, tetapi saya memilih jawaban WPAlchemy sebagai jawaban "resmi". Saya masih cukup baru untuk PHP / Wordpress bahwa saya belum super nyaman dengan kelas dan kait dan fungsi statis dan semacamnya. Saya berharap suatu hari akan menjadi mahir seperti kalian semua!
Nic Warmenhoven

Jawaban:

7

Sebagai penulis dari WPAlchemy , aku bias sedikit, tetapi Anda pada dasarnya memiliki baik model kerja yang digariskan untuk mengikuti tergantung pada apa yang pernah rute yang Anda pilih.

Namun, jika menggunakan WPAlchemy, Anda pada dasarnya akan melakukan sesuatu seperti berikut (langkah # 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.cssdapat berisi gaya yang Anda dapat gaya dengan formulir Anda dan custom/meta.phppada dasarnya adalah file HTML dengan isi FORMULIR dari kotak meta, dalam hal ini drop-down Anda, untuk menghasilkan drop-down Anda, Anda akan melakukan permintaan wp kustom untuk mendapatkan semua posting kustom Anda jenis. WPAlchemy memiliki beberapa fungsi pembantu khusus untuk membantu menciptakan elemen formulir Anda.

Ada dokumentasi tambahan untuk membantu Anda saat bekerja dalam templat.

Tujuan utama WPAlchemy adalah untuk tetap memegang kendali di tangan pengembang, mulai dari penataan (tampilan + nuansa) hingga definisi konten kotak meta.

Dan saya dan orang lain selalu bersedia membantu mereka yang berkomentar dan mengajukan pertanyaan.

farinspace
sumber
1
Jawaban yang bagus, tetapi mungkin saya menyarankan mengaitkan permintaan stylesheet tambahan tersebut secara khusus ke layar editor posting. Hal yang sama juga dapat dikatakan untuk penciptaan metabox, yang idealnya harus dikaitkan do_meta_boxesdengan beberapa logika kondisional atau sebagai alternatif ke add_meta_boxes_{%TYPE%}..
t31os
14

Hehe, kamu seorang pemula! Kami akan merobekmu sampai hancur ...!

j / k :) Kami menawarkan sambutan hangat untuk semua pemula di sini, senang memiliki Anda.

Jadi ini yang ketiga kalinya saya mendengar persyaratan ini, dua kali dari klien dan bukan lagi dari Anda (dan klien Anda.) Itu memberitahu saya bahwa ini adalah kebutuhan yang cukup umum.

Metabox Kustom WordPress menampilkan Tiga (3) Dropdown

Saya menyukai analisis Anda sehingga saya memutuskan untuk membuat kode kelas untuk membahas poin ke-2 Anda. Saya menyebutnya LittlePromoBoxeskarena saya tidak pernah bisa mengeluarkan lagu ini dari kepala saya, terima kasih kepada mereka . Pada dasarnya saya menggunakan kelas untuk merangkum untuk menghindari kemungkinan konflik penamaan dengan fungsi yang harus saya tulis.

Anda dapat meletakkan kelas ini di functions.phpfile tema Anda atau dalam file .PHP dari plugin yang mungkin Anda tulis (tapi jangan khawatir, ini terlihat jauh lebih kompleks daripada sebelumnya.)

Fungsi pertama on_load()adalah fungsi statis yang saya panggil di akhir deklarasi kelas untuk menginisialisasi tiga (3) kait yang Anda perlukan (fyi fungsi statis pada dasarnya adalah fungsi yang terkait dengan kelas , bukan instance) :

  1. The initkait untuk mendaftarkan promo-boxjenis pos,

  2. The add_meta_boxes_postkait untuk memungkinkan Anda untuk menentukan metabox, dan

  3. The wp_insert_post_datakait untuk memungkinkan Anda untuk menangkap kotak promo yang dipilih dan menyimpan ke database.

Masing-masing kait merujuk fungsi statis lain di kelas (ini adalah fungsi yang saya enkapsulasi dengan membuat kelas.)

Saya akan lewati menjelaskan action_init()fungsi dan fungsi make_labels()pembantu saya dengan asumsi Anda tahu cara mendaftarkan jenis posting berdasarkan pertanyaan Anda.

The action_add_meta_boxes_post()Fungsi register metabox menggunakan fungsi inti WordPress add_meta_box()dan saya sudah berkomentar parameter itu untuk menjelaskan mengapa saya melewati apa yang saya lulus untuk setiap. Fungsi panggilan balik the_little_promo_boxes_metabox()tentu saja merupakan fungsi statis lain dari kelas dan inilah yang sebenarnya menampilkan konten dalam metabox. Ini terutama menggunakan fungsi inti WordPress wp_dropdown_pages()untuk menampilkan daftar kotak promo (perhatikan bahwa itu akan menampilkan jenis posting lain selain 'halaman' tetapi hanya jika mereka ditandai sebagai sedang 'hierarchical'=>truedalam pendaftaran jenis posting mereka. Mengapa hanya hierarkis? Karena itu cara mereka menulisnya, itu sebabnya! :)

Karena kami menunjukkan tiga (3) dropdown, kami perlu memberikan masing-masing ID unik dalam HTML ( "promo_box_{$i}") tetapi nama yang sama dengan tanda kurung siku ( 'promo_boxes[]') sehingga PHP akan mengumpulkannya menjadi $_POSTvariabel dalam array (yang diakses WordPress untuk kami; Anda akan melihat bagaimana dalam satu menit) . Dan tentu saja kita perlu mengatur nilai yang dipilih ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])) jika memang salah satu nilai sebelumnya telah dipilih.

Saya juga menggunakan fungsi inti WordPress get_post_type_object()untuk menunjukkan cara mendapatkan label dari jenis posting, dan juga menggunakan fungsi inti WordPress get_post_meta()untuk mengambil array ID kotak promo dari menggunakan tombol bidang kustom '_promo_boxes' yang akan saya tunjukkan kepada Anda. untuk menyimpan berikutnya (perhatikan saya menggunakan garis bawah sebelumnya dalam nama '_promo_boxes'yang menyebabkan WordPress bersembunyi dari UI bidang kustom standar saat pengguna mengedit posting.) .

Fungsi terakhir untuk menggambarkan sebelum Anda melihat kode adalah filter_wp_insert_post_data()yang menerima data posting yang ada di parameter pertama ( $data) dan isi $_POSTarray berkat WordPress sebagai parameter kedua ( $postarr). Di dalam fungsi ini kami memanggil fungsi inti WordPress update_post_meta()dan mengekstrak array kotak promo ( $postarr['promo_boxes']) untuk menyimpan ke nilai bidang khusus untuk kunci '_promo_boxes'untuk posting yang ditentukan oleh $_POSTarray (yaitu $postarr['ID']).

Yang mengatakan, inilah kode untuk LittlePromoBoxeskelas:

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

Masih ada dua (2) fungsi statis yang belum disebutkan: get_promo_boxes()dan get_promo_box(); ini adalah fungsi pembantu untuk membantu Anda mengambil tulisan post_type='promo-box'dengan nomor urut 1..3. Tetapi untuk menjadikannya lebih banyak WordPress seperti di sini adalah dua fungsi pembungkus untuk ditambahkan ke functions.phpfile tema Anda (perhatikan bahwa Anda dapat mengirimkan sebuah postingan sebagai parameter tetapi Anda tidak harus melakukannya kecuali Anda menggunakan postingan berbeda dari yang ada di 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);
}

Sekarang Anda dapat memanggil satu atau kedua fungsi ini di single.phpfile tema Anda dengan kode yang mungkin terlihat seperti ini (kode ini bisa ditulis dalam satu lingkaran tetapi kebanyakan WordPress WordPress sepertinya suka menggandakan kode sehingga mereka dapat membacanya alih-alih menghilangkan redundansi Jadi, ketika di 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>';
?>
MikeSchinkel
sumber
1
Anda tidak pernah berhenti membuat saya takjub dengan jawaban Anda, upaya yang Anda lakukan untuk membuat kode, dan menjelaskan setiap langkah .. mengagumkan! .. (penyebutan Anda tentang kotak kecil juga membuat saya memikirkan salah satu serial TV favorit saya) ..
t31os
1
@ t31os - Terima kasih! Ketika saya mulai menjawab, saya tidak bisa menahan diri. Obsesif / kompulsif kurasa. Tapi setidaknya saya memanfaatkan dengan baik!
MikeSchinkel
@toscho - Terima kasih. Ya, saya jarang menambahkan humor sehingga ketika sampai pada saya, saya tidak bisa menolak. :-)
MikeSchinkel