การเพิ่มแอททริบิวของเพจ Metabox และเทมเพลทของเพจให้กับหน้าแก้ไขโพสต์?


14

( ผู้ดูแลหมายเหตุ:ชื่อเดิมคือ "ฉันจะเพิ่ม" คุณสมบัติของหน้า "และ / หรือ" เลือกคุณสมบัติของหน้า> แม่แบบ "เพื่อแก้ไข POSTS")

ปัจจุบัน WP อนุญาตเฉพาะการกำหนด "เทมเพลต" ให้กับหน้า (เช่นpost_type=='page') ฉันต้องการขยายฟังก์ชันการทำงานนี้ไปยังโพสต์ด้วย (เช่นpost_type=='post')

ฉันจะเพิ่มกล่องเมตา"แอททริบิวของเพจ"และตัวสลับเทมเพลตลงในเครื่องมือแก้ไขบทความได้อย่างไร

ฉันสมมติว่านี่คือรหัสที่ฉันจะใส่ลงในfunctions.phpธีมของฉัน

อัปเดต: ฉันจัดการเพื่อเพิ่มเมนูแบบเลื่อนลงของแม่แบบฮาร์ดโค้ดลงในเครื่องมือแก้ไขบทความของฉันโดยเพียงเพิ่มกล่อง html ที่เลือกลงในกล่องตัวเลือกเมตาที่กำหนดเองที่มีอยู่ของฉัน นี่คือรหัสที่ฉันใช้สำหรับสิ่งนั้น ...

add_meta_box('categorydiv2', __('Post Options'), 'post_categories_meta_box_modified', 'post', 'side', 'high');

และนี่คือฟังก์ชันที่เขียนตัวเลือกและกล่องเลือกเทมเพลต ...

//adds the custom categories box
function post_categories_meta_box_modified() {
    global $post;
    if( get_post_meta($post->ID, '_noindex', true) ) $noindexChecked = " checked='checked'";
    if( get_post_meta($post->ID, '_nofollow', true) ) $nofollowChecked = " checked='checked'";
?>
<div id="categories-all" class="ui-tabs-panel">
    <ul id="categorychecklist" class="list:category categorychecklist form-no-clear">
        <li id='noIndex' class="popular-category"><label class="selectit"><input value="noIndex" type="checkbox" name="chk_noIndex" id="chk_noIndex"<?php echo $noindexChecked ?> /> noindex</label></li> 
        <li id='noFollow' class="popular-category"><label class="selectit"><input value="noFollow" type="checkbox" name="chk_noFollow" id="chk_noFollow"<?php echo $nofollowChecked ?> /> nofollow</label></li>
    </ul>

    <p><strong>Template</strong></p> 
    <label class="screen-reader-text" for="page_template">Post Template</label><select name="page_template" id="page_template"> 
    <option value='default'>Default Template</option> 
    <option value='template-wide.php' >No Sidebar</option>
    <option value='template-salespage.php' >Salespage</option>
    </select>
</div>
<?php
}

และสุดท้ายรหัสเพื่อบันทึกค่าที่เลือกในการบันทึก ...

function save_post_categories_meta($post_id) {
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
    $noIndex = $_POST['chk_noIndex'];
    $noFollow = $_POST['chk_noFollow'];
    update_post_meta( $post_id, '_noindex', $noIndex );
    update_post_meta( $post_id, '_nofollow', $noFollow );
    return $post_id;
}

ตอนนี้ฉันเชื่อว่าสิ่งที่เหลืออยู่คือ (1) การจับภาพเทมเพลตที่เลือกและเพิ่มไปยังโพสต์เมตาสำหรับโพสต์นี้และ (2) การปรับเปลี่ยน index.php และ single.php เพื่อให้ใช้เทมเพลตที่เลือก


@Scott B : ดีฉันเขียนคำตอบทั้งหมดของฉันก่อนที่ฉันเห็นว่าคุณกำลังทำงานอยู่ด้วยและดูเหมือนว่าคุณได้ดำเนินการไปในทิศทางที่แตกต่างกันเล็กน้อยว่าคำถามดั้งเดิมของคุณไม่มีการติดตามและไม่มีตัวเลือกดัชนี หวังว่าสิ่งที่ฉันยังมีคุณค่าสำหรับคุณ ถ้าไม่เช่นนั้นอาจช่วยคนอื่นได้
MikeSchinkel

ใช่คุณตอบคำถามแล้ว ฉันใช้แทคที่แตกต่างกันเล็กน้อยเมื่อฉันรู้ว่าฉันไม่จำเป็นต้องแยกไดเรกทอรีและ hardcode ค่าสำหรับแม่แบบเฉพาะของฉัน ฉันจะยังคงต้องยืมรหัสบางส่วนของคุณเพื่อรับ WP จริง ๆ ใช้เทมเพลตที่กำหนดให้ถูกต้องสำหรับการโพสต์
Scott B

คำตอบ:


12

เกลียดที่จะเป็นผู้แบกรับข่าวร้าย แต่WordPress ทำการโค้ดฟังก์ชันของเทมเพลทของหน้าลงในประเภทโพสต์"หน้า"อย่างน้อยใน v3.0 (ที่อาจมีการเปลี่ยนแปลงในรุ่นอนาคต แต่ไม่มีความคิดริเริ่มเฉพาะที่ฉันตระหนักถึงการเปลี่ยนแปลง ดังนั้นนี่เป็นหนึ่งในไม่กี่ครั้งที่ฉันพยายามหาวิธีหลีกเลี่ยงบางสิ่งโดยไม่ต้องแฮ็คคอร์)

วิธีแก้ปัญหาที่ฉันเกิดขึ้นคือการคัดลอกรหัสที่เกี่ยวข้องจาก WordPress core และปรับเปลี่ยนตามความต้องการของเรา นี่คือขั้นตอน (หมายเลขบรรทัดมาจาก v3.0.1):

  1. คัดลอกpage_attributes_meta_box()ฟังก์ชั่นจากบรรทัด 535 /wp-admin/includes/meta-boxes.phpและปรับเปลี่ยนให้เหมาะสม

  2. รหัสadd_meta_boxesเบ็ดเพื่อเพิ่มสารที่สร้างขึ้นใน # 1

  3. คัดลอกget_page_templates()ฟังก์ชั่นจากบรรทัด 166 /wp-admin/includes/theme.php และปรับเปลี่ยนให้เหมาะสม

  4. คัดลอกpage_template_dropdown()ฟังก์ชั่นจากบรรทัด 2550 /wp-admin/includes/template.phpและแก้ไขให้เหมาะสม

  5. เพิ่มเทมเพลตโพสต์ในธีมของคุณ

  6. รหัสsave_postเบ็ดเพื่อเปิดใช้งานการจัดเก็บชื่อไฟล์แม่แบบโพสต์เมื่อบันทึก

  7. รหัสsingle_templateเบ็ดเพื่อเปิดใช้งานการโหลดแม่แบบโพสต์สำหรับโพสต์ที่เกี่ยวข้อง

ไปกับมัน!


1. คัดลอกpage_attributes_meta_box()ฟังก์ชั่น

ในฐานะที่เป็นขั้นตอนแรกของเราท่านต้องคัดลอกpage_attributes_meta_box()ฟังก์ชั่นจากบรรทัด 535 ของและฉันได้เลือกที่จะเปลี่ยนชื่อ/wp-admin/includes/meta-boxes.php post_template_meta_box()เนื่องจากคุณขอเฉพาะเทมเพลตของหน้าเว็บฉันจึงตัดรหัสเพื่อระบุโพสต์หลักและระบุลำดับที่ทำให้รหัสง่ายขึ้นมาก ฉันยังเลือกที่จะใช้ postmeta สำหรับสิ่งนี้แทนที่จะพยายามนำpage_templateคุณสมบัติของวัตถุกลับมาใช้ใหม่เพื่อหลีกเลี่ยงและความไม่ลงรอยกันที่อาจเกิดขึ้นจากการมีเพศสัมพันธ์โดยไม่ได้ตั้งใจ ดังนั้นนี่คือรหัส:

function post_template_meta_box($post) {
  if ( 'post' == $post->post_type && 0 != count( get_post_templates() ) ) {
    $template = get_post_meta($post->ID,'_post_template',true);
    ?>
<label class="screen-reader-text" for="post_template"><?php _e('Post Template') ?></label><select name="post_template" id="post_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php post_template_dropdown($template); ?>
</select>
<?php
  } ?>
<?php
}

2. รหัสadd_meta_boxesเบ็ด

ขั้นต่อไปคือการเพิ่ม metabox โดยใช้add_meta_boxeshook:

add_action('add_meta_boxes','add_post_template_metabox');
function add_post_template_metabox() {
    add_meta_box('postparentdiv', __('Post Template'), 'post_template_meta_box', 'post', 'side', 'core');
}

3. คัดลอกget_page_templates()ฟังก์ชั่น

ฉันคิดว่ามันจะทำให้รู้สึกถึงความแตกต่างระหว่างแม่แบบหน้าและหลังแม่แบบจึงต้องมีget_post_templates()ฟังก์ชั่นบนพื้นฐานget_page_templates()จากบรรทัด /wp-admin/includes/theme.php166 แต่แทนที่จะใช้Template Name:เครื่องหมายซึ่งแม่แบบหน้าใช้ฟังก์ชันนี้ใช้Post Template:เครื่องหมายแทนซึ่งคุณสามารถดูด้านล่าง

ผมก็กรองออกตรวจสอบfunctions.php (ไม่แน่ใจว่าget_page_templates()เคยทำงานได้อย่างถูกต้องโดยไม่ต้องว่า แต่สิ่งที่!)และสิ่งเดียวที่เหลือคือการอ้างอิงการเปลี่ยนแปลงคำpageเพื่อpostสำหรับการอ่านการบำรุงรักษาลงที่ถนน:

function get_post_templates() {
  $themes = get_themes();
  $theme = get_current_theme();
  $templates = $themes[$theme]['Template Files'];
  $post_templates = array();

  if ( is_array( $templates ) ) {
    $base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );

    foreach ( $templates as $template ) {
      $basename = str_replace($base, '', $template);
      if ($basename != 'functions.php') {
        // don't allow template files in subdirectories
        if ( false !== strpos($basename, '/') )
          continue;

        $template_data = implode( '', file( $template ));

        $name = '';
        if ( preg_match( '|Post Template:(.*)$|mi', $template_data, $name ) )
          $name = _cleanup_header_comment($name[1]);

        if ( !empty( $name ) ) {
          $post_templates[trim( $name )] = $basename;
        }
      }
    }
  }

  return $post_templates;
}

4. คัดลอกpage_template_dropdown()ฟังก์ชั่น

คัดลอกpage_template_dropdown()มาจากบรรทัด 2550 ของ/wp-admin/includes/template.phpเพื่อสร้างpost_template_dropdown()และเปลี่ยนเป็นสายget_post_templates()แทน:

function post_template_dropdown( $default = '' ) {
  $templates = get_post_templates();
  ksort( $templates );
  foreach (array_keys( $templates ) as $template )
    : if ( $default == $templates[$template] )
      $selected = " selected='selected'";
    else
      $selected = '';
  echo "\n\t<option value='".$templates[$template]."' $selected>$template</option>";
  endforeach;
}

5. เพิ่มเทมเพลตโพสต์

ขั้นตอนต่อไปคือการเพิ่มเทมเพลตโพสต์สำหรับการทดสอบ ใช้Post Template:เครื่องหมายที่กล่าวถึงในขั้นตอนที่ 3 คัดลอกsingle.phpจากชุดรูปแบบของคุณไปยังsingle-test.phpและเพิ่มส่วนหัวของความคิดเห็นต่อไปนี้ ( อย่าลืมแก้ไขบางสิ่งsingle-test.phpเพื่อให้คุณสามารถบอกได้ว่ากำลังโหลดแทนsingle.php) :

/**
 * Post Template: My Test Template
 */

เมื่อคุณทำตามขั้นตอน # 1 ถึง # 5 แล้วคุณจะเห็นmetabox "เทมเพลตโพสต์"ปรากฏในหน้าเครื่องมือแก้ไขบทความ:

เทมเพลตโพสต์ของ Metabox มีลักษณะอย่างไรเมื่อเพิ่มเข้ากับ WordPress 3.0
(ที่มา: mikeschinkel.com )

6. รหัสsave_postเบ็ด

หลังจากที่คุณมีตัวแก้ไขกำลังสองคุณต้องบันทึกชื่อไฟล์เทมเพลตของหน้าเป็น postmeta เมื่อผู้ใช้คลิก "เผยแพร่" นี่คือรหัสสำหรับ:

add_action('save_post','save_post_template',10,2);
function save_post_template($post_id,$post) {
  if ($post->post_type=='post' && !empty($_POST['post_template']))
    update_post_meta($post->ID,'_post_template',$_POST['post_template']);
}

7. รหัสsingle_templateเบ็ด

และสุดท้ายคุณต้องได้รับ WordPress ใช้เทมเพลตโพสต์ใหม่ของคุณ คุณทำอย่างนั้นโดยการขอsingle_templateและส่งคืนชื่อเทมเพลตที่คุณต้องการสำหรับโพสต์เหล่านั้นที่ได้รับมอบหมาย:

add_filter('single_template','get_post_template_for_template_loader');
function get_post_template_for_template_loader($template) {
  global $wp_query;
  $post = $wp_query->get_queried_object();
  if ($post) {
    $post_template = get_post_meta($post->ID,'_post_template',true);
    if (!empty($post_template) && $post_template!='default')
      $template = get_stylesheet_directory() . "/{$post_template}";
  }
  return $template;
}

และที่เกี่ยวกับมัน!

หมายเหตุที่ฉันไม่ได้คำนึงถึงประเภทกำหนดเองโพสต์post_type=='post'เท่านั้น ในความเห็นของฉันเกี่ยวกับประเภทโพสต์ที่กำหนดเองจะต้องมีความแตกต่างระหว่างประเภทโพสต์ที่แตกต่างกันและในขณะที่ไม่ยากเกินไปฉันไม่ได้ลองที่นี่


ที่ดี! ฉันเข้าสู่โหมดสลีปด้วยโค้ดที่เกือบสมบูรณ์ในตัวแก้ไขด้วยวิธีเดียวกันกับการคัดลอกฟังก์ชั่น WordPress เริ่มต้น (มันเสร็จสมบูรณ์ แต่ฉันจะไม่โพสต์มันตั้งแต่ฉันไม่ได้ทดสอบ) :)
sorich87

@ sorich87 - คุณรู้คำพูดเดิมว่า"คุณงีบหลับคุณหลวม!" อย่างจริงจังแม้ว่าล้อเล่นเท่านั้น มีวิธีการที่สมเหตุสมผลเพียงวิธีเดียวเท่านั้นที่จะทำงานได้ดังนั้นจึงไม่น่าแปลกใจที่รหัสของคุณจะเหมือนกัน!
MikeSchinkel

ไมค์คุณยังคงประหลาดใจ ขอบคุณมากที่สละเวลาเพื่อไขปัญหานี้
Scott B

@ sorich87 - ขอบคุณที่ทำงานกับมัน ฉันซาบซึ้งในความพยายาม
Scott B

1
@Scott B : ไม่มีปัญหาดีใจที่ฉันสามารถช่วยได้ ฉันมองหาคำถามทั่วไปที่สมเหตุสมผลซึ่งอาจช่วยคนจำนวนมากและพยายามตอบคำถามเหล่านั้นไม่เพียง แต่คนที่ถามคำถามเท่านั้น แต่สำหรับผู้ที่อาจมาด้วย
MikeSchinkel

0

Wordpress ช่วยให้คุณเพิ่ม Meta to Categories โดยใช้ปลั๊กอิน:

ในการทำเช่นนี้คุณต้องเพิ่มหนึ่งในส่วนขยายต่าง ๆ ที่เพิ่มเมตาลงในหมวดหมู่ (การลอกเลียนสิ่งที่หน้าออกนอกกรอบ) Simple Term Metaทำงานได้ดี

NB WordPress 3.x เป็นสิ่งจำเป็นสำหรับการขยายหมวดหมู่

หลังจากนั้นคุณสามารถใช้:

  • add_term_meta
  • update_term_meta
  • get_term_meta

ใช้ Function.php เพื่อเพิ่มวิธีการในสิ่งที่คุณต้องการเช่น

add_action('category_add_form_fields', 'category_metabox_add', 10, 1);

function category_metabox_add($tag) { ?>
    <div class="form-field">
        <label for="image-url"><?php _e('Image URL') ?></label>
        <input name="image-url" id="image-url" type="text" value="" size="40" aria-required="true" />
        <p class="description"><?php _e('This image will be the thumbnail shown on the category page.'); ?></p>
    </div>
<?php } 

add_action('created_category', 'save_category_metadata', 10, 1);

function save_category_metadata($term_id)
{
    if (isset($_POST['image-url'])) 
        update_term_meta( $term_id, 'image-url', $_POST['image-url']);                  
}

การโทรสาขาใหม่ในธีมเป็นเรื่องง่าย:

<?php echo get_term_meta(get_query_var('cat'), 'image-url', true); ?>

รายละเอียดเพิ่มเติมและตัวอย่าง: http://www.wphub.com/adding-metadata-taxonomy-terms/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.