Пользовательское поле / мета, заполненное выпадающими списками существующих сообщений?

11

(Мой первый вопрос WP когда-либо задавался! Будьте нежны!)

Я строю сайт, который в основном страницы (то есть, статические), используя WP в качестве CMS. Внизу нескольких страниц появятся 1, 2 или 3 «промо-коробки» - в основном кнопки-изображения, которые ссылаются на другие части сайта. Хотя на каждой странице будет отображаться только до 3 промо-боксов, на выбор будет ~ 30 разных.

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

Мне кажется, это должно работать так:

  • Создайте собственный тип поста под названием «промо-бокс». (Хотя это также может быть тег для обычных сообщений.)
  • Используйте такой инструмент, как Шаблон настраиваемого поля, чтобы создать раскрывающийся список в редакторе страниц, где значения параметров раскрывающегося списка динамически генерируются из списка всех существующих сообщений промо-бокса. ( Это часть, которую я не знаю, как сделать. )
  • Получите доступ к полученным метаданным (номер сообщения - действительно все, что мне нужно, тогда я могу получить все остальное) в шаблоне страницы.

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

Совет? Является ли один из вышеперечисленных инструментов правильным решением для меня, и мне просто нужно выяснить это? Я что-то здесь упускаю?

Ник Варменховен
источник
Вау, спасибо за поддержку! Я надеюсь, что я ни в коем случае не обесцениваю время и щедрость MikeSchinkel, но я выбрал ответ 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-файл с содержимым FORM мета-блока, в данном случае с раскрывающимся списком, чтобы создать раскрывающийся список, вы должны выполнить настраиваемый wp-запрос, чтобы получить все ваши собственные сообщения. типы. В WPAlchemy есть несколько специальных вспомогательных функций, помогающих создавать элементы формы.

Существует дополнительная документация, которая поможет вам при работе с шаблоном.

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

И я, и другие всегда готовы помочь тем, кто комментирует и задает вопросы.

farinspace
источник
1
Хороший ответ, но могу ли я предложить подключить этот дополнительный запрос таблицы стилей специально к экрану редактирования сообщений. То же самое можно сказать и о создании метабокса, который в идеале должен быть связан do_meta_boxesс некоторой условной логикой или, альтернативно, с add_meta_boxes_{%TYPE%}
t31os
14

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

j / k :) Мы предлагаем теплый прием всем новичкам здесь, рад, что вы.

Поэтому я слышу это требование в третий раз, дважды от клиентов, а не от вас (и вашего клиента). Это говорит о том, что это достаточно распространенная потребность.

WordPress Custom Metabox с тремя (3) выпадающими

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

Вы можете поместить этот класс в functions.phpфайл вашей темы или в файл .PHP плагина, который вы, возможно, пишете (но не волнуйтесь, он выглядит намного сложнее, чем он есть).

Первая функция on_load()- это статическая функция, которую я вызываю в конце объявления класса для инициализации трех (3) хуков, которые вам понадобятся (например, статические функции - это функции, связанные с классом , а не с экземпляром) :

  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файл вашей темы (обратите внимание, что вы можете передавать сообщение в качестве параметра, но вам это не нужно, если вы не используете сообщение, отличное от того, что в 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>';
?>
MikeSchinkel
источник
1
Вы не перестаете удивлять меня своими ответами, усилиями, которые вы делаете для создания кода, и объясняете каждый шаг ... потрясающе! .. (ваше упоминание о маленьких коробочках также заставляет меня задуматься об одном из моих любимых сериалов) ..
t31os
1
@ t31os - Спасибо! Когда я начинаю отвечать, я просто не могу остановиться. Наверное, навязчивый / навязчивый. Но, по крайней мере, я помогаю!
MikeSchinkel
@toscho - Спасибо. Да, я так редко добавляю в юмор, что когда дело доходит до меня, я не могу сопротивляться. :-)
MikeSchinkel