Спеціальне поле / мета, заповнене спадом існуючих публікацій?


11

(Перше моє запитання WP, яке я коли-небудь задавав! Будь ласкавим!)

Я будую сайт, який в основному представляє собою сторінки (тобто статичні), використовуючи WP як CMS. У нижній частині декількох сторінок з'являться 1, 2 або 3 "промо-вікна" - в основному зображення кнопок, які посилаються на інші частини сайту. Хоча на будь-якій сторінці з’являться лише до 3 промо-скриньок, на вибір буде розміщено ~ 30 різних.

Коли мій клієнт створює нову сторінку, я хотів би, щоб він міг вибрати рекламні коробки із чогось схожого на випадаючий список усіх можливих рекламних вікон.

Мені здається, це має працювати так:

  • Створіть спеціальний тип публікації під назвою "промо-коробка". (Хоча це так само легко може бути тегом для регулярних публікацій.)
  • Використовуйте такий інструмент, як користувальницький шаблон шаблону поля, щоб створити спадне меню в редакторі сторінок, де значення параметрів випадаючого меню динамічно генеруються зі списку всіх існуючих публікацій рекламних вікон. ( Це частина, яку я не знаю, як це зробити. )
  • Отримайте доступ до отриманих метаданих (номер пошти - це все, що мені потрібно, тоді я можу отримати все інше) на шаблоні сторінки.

На основі відповідей на інші запитання тут я переглянув WPAlchemy MetaBox, Posts-2-Posts та SLT користувальницькі поля, але, зізнаюся, документація для кожного з них трохи причудливіша, ніж я, тому я не заглиблювався занадто глибоко

Поради? Чи є одним із перерахованих вище інструментів правильне рішення для мене, і я просто мушу це розібратися? Я щось тут пропускаю?


О, дякую за всю підтримку! Я сподіваюся, що я в будь-якому разі не знецінюю час і щедрість Майка Шчінкеля, але вибрав відповідь WPAlchemy як "офіційну" відповідь. Я все ще достатньо новий для PHP / Wordpress, що мені ще не дуже зручно з класами, гачками та статичними функціями та ін. Я сподіваюся, що коли-небудь буде настільки ж досвідченим, як і всі ви!
Нік Варменховен

Відповіді:


7

Як автор з WPAlchemy , я трохи упередженості, але ви , по суті є робоча модель добре змалював слідувати в залежності від того, що коли - небудь шлях ви обираєте.

Однак, якщо ви використовуєте WPAlchemy, ви в основному зробите щось подібне (крок №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може містити стилі, за допомогою яких можна custom/meta.phpнадати форму, і це, по суті, HTML-файл із вмістом ФОРМИ мета-вікна, в цьому випадку випадає, щоб генерувати спадне меню, ви зробили б спеціальний wp-запит, щоб отримати всю вашу власну публікацію типи. WPAlchemy має деякі спеціальні допоміжні функції для сприяння у створенні елементів форми.

Існує додаткова документація, яка допоможе вам працювати в шаблоні.

Основна мета WPAlchemy полягала в тому, щоб тримати контроль в руках розробника, від стилізації (look + feel) до визначення вмісту мета-коробки.

І я, і інші завжди готові допомогти тим, хто коментує і задає питання.


1
Приємна відповідь, але чи можу я запропонувати підключити цей додатковий запит стилів саме на екран редагування публікацій. Те саме можна сказати і для створення метабоксу, що в ідеалі слід підключити за do_meta_boxesдопомогою якоїсь умовної логіки або альтернативно add_meta_boxes_{%TYPE%}..
t31os

14

Хе-хе, ти новачок! Ми зірвемо тебе на клаптики ...!

j / k :) Ми пропонуємо теплий прийом всім новачкам тут, радий вас мати.

Отже, це вже 3-й раз, коли я чув цю вимогу двічі від клієнтів, і не від вас (і вашого клієнта.), Що говорить мені, що це досить загальна потреба.

WordPress користувацький метабокс із трьома (3) спадами

Мені сподобався ваш аналіз, тому я вирішив зашифрувати клас, щоб вирішити вашу другу точку. Я назвав це, LittlePromoBoxesтому що я ніколи не можу отримати цю пісню з голови, завдяки їм . В основному я використовую клас для інкапсуляції, щоб інакше уникнути потенційних конфліктів імен з функціями, які мені потрібно було б написати.

Ви можете помістити цей клас у functions.phpфайл своєї теми або у файл .PHP плагіна, про який ви могли писати (але не хвилюйтеся, він виглядає набагато складніше, ніж є).

Перша функція on_load()- це статична функція, яку я закликаю в кінці декларації класу, щоб ініціалізувати три (3) гаки, які вам знадобляться (fyi статичні функції - це по суті функції, пов'язані з класом , а не екземпляром) :

  1. initКрюк , щоб зареєструвати promo-boxтип запису,

  2. add_meta_boxes_postКрюк , щоб дозволити вам визначити METABOX, і

  3. wp_insert_post_dataКрюк , щоб дозволити вам захопити вибрані промо коробки і зберегти в базі даних.

Кожен з цих гаків посилається на іншу статичну функцію в класі (це були функції, які я інкапсулював, створюючи клас.)

Я пропускаю опис action_init()функції та моєї make_labels()функції помічника, припускаючи, що ви знаєте, як зареєструвати тип публікації на основі ваших запитань.

action_add_meta_boxes_post()Фіксуючи METABOX з допомогою функції ядра WordPress , add_meta_box()і я помітив , що це параметри , щоб пояснити , чому я пройшов , що я проходив повз кожного з них . Звичайно, функція зворотного виклику the_little_promo_boxes_metabox()- це ще одна статична функція класу, і саме вона відображає вміст у метабоксі. В основному він використовує основну функцію WordPress wp_dropdown_pages()для відображення списку промо-вікон (зауважте, що він відображатиме інші типи публікацій, окрім "сторінки", але лише якщо вони позначені як такі, що зареєстровані 'hierarchical'=>trueв їх публікації. Чому лише ієрархічна? Тому що саме так вони написав, ось чому! :)

Оскільки ми показуємо три (3) спадні місця, нам потрібно надати кожному унікальний ідентифікатор у HTML ( "promo_box_{$i}"), але те саме ім’я з квадратними дужками ( 'promo_boxes[]'), щоб PHP збирав їх у масив всередині $_POSTзмінної (який WordPress отримує для нас; ви побачите, як через хвилину) . І звичайно, нам потрібно встановити вибране значення ( (empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])), якщо дійсно було вибрано одне із значень раніше.

Я також використовував основну функцію WordPress, get_post_type_object()щоб показати, як отримати мітки від типу публікації, а також за допомогою основної функції WordPress get_post_meta()отримати масив ідентифікаторів промо-скриньки за допомогою користувацького полевого ключа "_promo_boxes", який я покажу вам щоб зберегти наступне (примітка я використав попереднє підкреслення в назві , '_promo_boxes'яке викликає WordPress , щоб приховати від стандартного інтерфейсу поля , коли користувач редагує запис.) .

Остання функція, яка описується перед тим, як побачити код, - це те, filter_wp_insert_post_data()що отримує наявні дані про пост у першому параметрі ( $data) та вміст $_POSTмасиву завдяки WordPress як другому параметру ( $postarr). Всередині цієї функції ми викликаємо основну функцію WordPress update_post_meta()і витягуємо масив промо-скриньок ( $postarr['promo_boxes']), щоб зберегти значення спеціального поля для ключа '_promo_boxes'для повідомлення, визначеного $_POSTмасивом (тобто $postarr['ID']).

Це сказав, ось код для 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();

Є ще дві (2) статичні функції, які ще не згадуються: get_promo_boxes()і get_promo_box(); це допоміжні функції, які допоможуть вам отримати посади post_type='promo-box'за порядковими номерами 1..3. Але щоб зробити їх більш WordPress, як ось, є дві функції обгортки, які потрібно додати до functions.phpфайлу вашої теми (зауважте, що ви можете передати публікацію як параметр, але цього не потрібно, якщо ви не використовуєте інший пост, ніж той, що знаходиться в 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);
}

Тепер ви можете викликати одну або обидві ці функції у вашому single.phpфайлі теми з кодом, який може виглядати приблизно так (цей код міг бути написаний у циклі, але більшість темерів WordPress, схоже, люблять дублювати код, щоб вони могли прочитати його замість усунення надмірності . Отже, коли в Римі ...):

<?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
Ви ніколи не перестаєте дивувати мене своїми відповідями, зусиллями, які ви докладаєте, щоб створити код, і пояснюйте кожен крок .. приголомшливий! .. (Ваша згадка про маленькі скриньки також змушує мене думати про один із моїх улюблених серіалів) ..
t31о

1
@ t31os - Дякую! Коли я починаю відповідати, я просто не можу зупинити себе. Нав'язливий / нав'язливий я здогадуюсь. Але принаймні я приношу користь!
MikeSchinkel

@toscho - Дякую Так, я так рідко додаю гумору, що коли до мене доходить, я не можу чинити опір. :-)
MikeSchinkel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.