問題描述

(我的第一個 WP 問題曾經問過!温柔!)

我正在構建一個主要是頁面 (即靜態) 的網站,使用 WP 作為 CMS 。在幾頁的底部,將出現 1,2 或 3 個”promo boxes” – 基本上 button-images 鏈接到站點的其他部分。雖然在任何給定的頁面上只能出現 3 個促銷框,但可以選擇 30 個不同的促銷框。

當我的客户創建一個新頁面時,我希望他能夠從所有可能的促銷框的下拉列表中選擇促銷框。

看來我應該這樣工作:

  • 創建名為”promo-box” 的自定義帖子類型。 (儘管它可以很容易地成為常規帖子的標籤。)

  • 使用類似 Custom Field Template 的工具在頁面編輯器上創建一個下拉列表,其中從所有現有的 promo-box 帖子的列表中動態生成下拉選項的值。 (這是我不知道該怎麼做的部分)

  • 訪問生成的元數據 (發佈號真的是我需要的,然後我可以得到所有其他) 在頁面模板上。

根據對其他問題的回應,我已經初步看過 WPAlchemy MetaBox,Post-2-Posts 和 SLT Custom Fields,但是我承認每個文檔的文檔比我都微乎其微,所以我還沒有被挖掘出來太深了

建議嗎?上面的工具之一是我正確的解決方案,我只需要弄清楚?我在這裏遺漏了什麼嗎?

最佳解決方案

作為 WPAlchemyauthor,我有點偏見,但您基本上有一個很好的工作模式概述遵循,根據你選擇的路線。

但是,如果使用 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 樣式,custom/meta.php 本質上是一個具有元數據框的 FORM 內容的 HTML 文件,在這種情況下,您的下拉菜單將生成您的下拉菜單,您將執行一個自定義 wp 查詢來獲取所有的自定義帖子類型。 WPAlchemy 有一些特殊的幫助函數來幫助創建表單元素。

另外還有一個 documentation 來幫助你在模板中工作。

WPAlchemy 的主要目標是將開發者掌握控制權,從造型 (外觀+感覺) 到元框內容定義。

我和他人總是樂意幫助那些發表評論和提問的人。

次佳解決方案

呵呵,你是個新手!我們要撕裂你的碎片…!

j /k :) 我們熱烈歡迎這裏的所有新手,很高興有你。

所以這是我第三次聽到這個要求,兩次來自客户,不再來自你 (和你的客户) 。這告訴我這是一個很常見的需要。

我喜歡你的分析,所以我決定編寫一個類來解決你的第二點。我調用 LittlePromoBoxes,因為我不能讓 this song 出來,感謝 them 。基本上我使用類來封裝,以避免與我需要編寫的函數發生潛在的命名衝突。

您可以將此類放在主題的 functions.php 文件中,或者在您可能正在編寫的插件的.PHP 文件中 (但不要擔心,它看起來比它複雜得多) 。

第一個函數 on_load()是一個靜態函數,我在類聲明的末尾調用初始化你需要的三 (3) 個鈎子 (fyi 靜態函數本質上是 functions related to the class,而不是實例):

  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 核心函數 add_meta_box()註冊 metabox,我已經評論過它的參數,以解釋為什麼我通過了我為每個通過了。回調函數 the_little_promo_boxes_metabox()當然是該類的另一個靜態函數,它實際上是在 metabox 中顯示的內容。它主要使用 WordPress 核心函數 wp_dropdown_pages()來顯示一個促銷框列表 (注意它將顯示除了’page’ 之外的其他帖子類型,但只有在他們的帖子類型註冊中被標記為'hierarchical'=>true,為什麼只有層次結構?因為這樣寫了,這就是為什麼!:)

由於我們顯示了三 (3) 個下拉列表,所以我們需要在 HTML("promo_box_{$i}") 中給出每個唯一的 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) 中的現有帖子數據以及 $_POST 數組的內容,這得益於 WordPress 作為第二個參數 ($postarr) 。在這個功能裏面,我們稱之為 WordPress 核心函數 update_post_meta(),並提取促銷框數組 ($postarr['promo_boxes']),以保存 $_POST 數組 (即 $postarr['ID']) 指定的帖子'_promo_boxes'的自定義字段值。

也就是説,這是 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'的帖子。但是要讓他們更多的 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>';
?>

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。