通过现有帖子的下拉列表填充自定义字段/元?


11

(我问过的第一个WP问题!请保持柔和!)

我正在使用WP作为CMS构建一个主要是页面(即静态)的网站。在几个页面的底部,将出现1个,2个或3个“促销框”-基本上是链接到网站其他部分的按钮图像。尽管在给定的页面上最多只会显示3个促销框,但大约有30种不同的促销框可供选择。

当客户创建新页面时,我希望他能够从诸如所有可能的促销框的下拉列表中选择促销框。

在我看来这应该像这样工作:

  • 创建一个名为“ promo-box”的自定义帖子类型。(尽管它可以很容易地成为常规帖子的标签。)
  • 使用“ 自定义字段模板”之类的工具在页面编辑器上创建一个下拉菜单,该下拉菜单的值是从所有现有促销箱帖子的列表中动态生成的。(这是我不知道该怎么做的部分。
  • 访问页面模板上的结果元数据(帖子号实际上是我所需要的,然后我可以获得所有其他信息)。

根据对此处其他问题的回答,我初步了解了WPAlchemy MetaBox,Posts-2-Posts和SLT自定义字段,但我承认它们的文档比我略有些怪异,所以我没有深入研究太深了。

忠告?以上工具之一对我来说是正确的解决方案,而我只需要弄清楚吗?我在这里想念什么吗?


哇,谢谢大家的支持!我希望无论如何我都不会贬低MikeSchinkel的时间和慷慨,但我选择WPAlchemy答案作为“官方”答案。我对PHP / Wordpress还是很陌生,对类,钩子和静态函数等还不太满意。我希望有一天能像你们一样精通!
Nic Warmenhoven,2010年

Answers:


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本质上是带有meta框的FORM内容的HTML文件,在这种情况下,您的下拉菜单将生成自定义wp查询以获取所有自定义帖子,以生成下拉菜单类型。WPAlchemy具有一些特殊的辅助功能,以帮助您创建表单元素。

在使用模板时,还有其他文档可为您提供帮助。

WPAlchemy的主要目标是将控制权掌握在开发人员手中,从样式(外观+感觉)到元框内容定义。

我自己和其他人总是愿意帮助发表评论和提问的人。


1
不错的答案,但我建议将这个额外的样式表请求专门挂到帖子编辑屏幕上。对于metabox的创建也可以说同样的话,理想情况下,应该do_meta_boxes使用一些条件逻辑将其挂接到钩子上,或者将钩子钩到add_meta_boxes_{%TYPE%}..
t31os 2010年

14

呵呵,你是新手!我们要撕成碎片...!

j / k :) 我们热烈欢迎所有新手在这里感到高兴。

因此,这是我第三次听到此要求,这是两次来自客户,而不是您(以及您的客户)。这告诉我这是相当普遍的需求。

WordPress自定义Metabox显示三(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()函数使用WordPress核心函数注册metabox,add_meta_box()并且我已注释了它的参数以解释为什么我传递了每个传递的内容。回调函数the_little_promo_boxes_metabox()当然是该类的另一个静态函数,它实际上是在metabox中显示内容的函数。它主要使用WordPress核心功能wp_dropdown_pages()显示促销框列表(请注意,它将显示除“页面”之外的其他帖子类型,但前提是它们被标记为'hierarchical'=>true处于其帖子类型注册中。写了,这就是为什么!!

由于我们显示了三(3)个下拉列表,因此我们需要在HTML("promo_box_{$i}")中为每个ID赋予唯一的ID,但用方括号('promo_boxes[]')赋予相同的名称,以便PHP将它们收集到$_POST变量内部的数组中(WordPress可以为我们访问该数组;您将在一分钟内看到如何)。当然,(empty($promo_boxes[$i]) ? 0 : $promo_boxes[$i])如果确实曾经选择过其中一个值,则需要设置所选值()。

我还使用了WordPress核心功能get_post_type_object()来展示如何从帖子类型中获取标签,还使用WordPress核心功能get_post_meta()来使用自定义字段键“ _promo_boxes”来检索促销框ID数组,我将向您展示保存下一个(请注意,我在名称中使用了下划线,'_promo_boxes'当用户编辑帖子时,它会导致WordPress从标准自定义字段UI中隐藏。)

在看到代码之前,要描述的最后一个函数是filter_wp_insert_post_data(),在第一个参数($data)中接收现有的帖子数据,并通过$_POSTWordPress作为第二个参数($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 themers似乎都希望复制代码,以便他们可以读取它而不是消除冗余)因此,在罗马时...):

<?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
您将永远不会停止给我答案,让您惊叹于创建代码,并解释每个步骤..太棒了!..(您提到的小盒子也让我想到了我最喜欢的电视连续剧之一)。
t31os 2010年

1
@ t31os-谢谢!当我开始回答时,我无法阻止自己。我猜想强迫症。但是至少我要善加利用!
MikeSchinkel 2010年

@toscho-谢谢。是的,我很少加幽默,以至于我无法抗拒。:-)
MikeSchinkel 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.