最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Custom field values deleted when trashing custom post type

programmeradmin1浏览0评论

I've created a custom post type with 2 custom fields attached to it... When I create a post of this type and fill in the custom fields, the data is, in fact, saved to the db... However, if I trash one of them, then that post's custom fields data is deleted from the database.

I thought trashing was just supposed to basically change the post_status to "trash" so it's out of view unless you actually delete it permanently?

If that's the case, why am I losing my custom fields data when I trash an item?

Here's all the relevant code for the above question:

<?php
add_action('admin_init', 'wpg_add_testimonial_author');
function wpg_add_testimonial_author() {
  add_meta_box('wpg_testimonial_author', __('Author Information', 'quotable'), 'wpg_testimonial_author', 'testimonials', 'side', 'low');
}

function wpg_testimonial_author() {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];
  ?>
  <p>
    <label><?php _e("Author's Name:", 'quotable'); ?></label>
    <input name="testimonial_author_name" value="<?php echo $testimonial_author_name; ?>" />
  </p>
  <p>
    <label><?php _e('Attribution Link:', 'quotable'); ?></label>
    <input name="testimonial_author_link" value="<?php echo $testimonial_author_link; ?>" />
  </p>
  <?php
}

function wpg_save_testimonial_author() {
  global $post;
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return $post_id;
  }
  if (defined('DOING_AJAX')) {
    return;
  }
  update_post_meta($post->ID, 'testimonial_author_name', $_POST['testimonial_author_name']);
  update_post_meta($post->ID, 'testimonial_author_link', $_POST['testimonial_author_link']);
}
add_action('save_post', 'wpg_save_testimonial_author');

function wpg_row_actions() {
  global $post;
  if($post->post_type == 'page') {
    if(!current_user_can('edit_page')) {
      return;
    }
  }
  else {
    if(!current_user_can('edit_post')) {
      return;
    }
  }
  if($post->post_status == 'trash') {
    $actionLinks  = '<div class="row-actions"><span class="untrash"><a title="'.__('Restore this item', 'quotable').'" href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=untrash', 'untrash-'.$post->post_type.'_'.$post->ID).'">'.__('Restore', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="trash"><a href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=delete', 'delete-'.$post->post_type.'_'.$post->ID).'" title="'.__('Delete this item permanently', 'quotable').'" class="submitdelete">'.__('Delete Permanently', 'quotable').'</a></span>';
  }
  else {
    $actionLinks  = '<div class="row-actions"><span class="edit"><a title="'.__('Edit this item', 'quotable').'" href="'.get_admin_url().'post.php?post='.$post->ID.'&action=edit">'.__('Edit', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="inline hide-if-no-js"><a title="'.__('Edit this item inline', 'quotable').'" class="editinline" href="#">'.__('Quick Edit', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="trash"><a href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=trash', 'trash-'.$post->post_type.'_'.$post->ID).'" title="'.__('Move this item to the Trash', 'quotable').'" class="submitdelete">'._x('Trash', 'verb (ie. trash this post)', 'quotable').'</a></span>';
  }
  return $actionLinks;
}

function wpg_edit_testimonials_columns($columns) {
  $columns = array(
    'cb' => '<input type="checkbox" />',
    'testimonial_author' => __('Author', 'quotable'),
    'testimonial_text' => __('Testimonial', 'quotable'),
    'attribution_link' => __('Attribution Link', 'quotable'),
    'date' => __('Date Added', 'quotable')
  );
  return $columns;
}

function wpg_manage_testimonials_columns($column, $post_id) {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];

  $wpg_row_actions  = wpg_row_actions();

  switch($column) {
    case 'testimonial_author':
      echo $testimonial_author_name.$wpg_row_actions;
    break;

    case 'testimonial_text':
      echo $post->post_content;
    break;

    case 'attribution_link':
      echo $testimonial_author_link;
    break;

    default :
      break;
    }
  }
  add_filter('manage_edit-testimonials_columns', 'wpg_edit_testimonials_columns');
  add_action('manage_testimonials_posts_custom_column', 'wpg_manage_testimonials_columns', 10, 2);

The custom post type doesn't support the "title" portion of posts, so it's not included as one of the columns in the edit posts page. Therefore, I had to hack my own version of the row_actions() function to enable the edit/quick edit/trash links when each post is hovered.

All of the functionality works as it should... Except that the "testimonial author" and "attribution link" values are deleted from the database when moving a post to the trash. No idea why...

I've created a custom post type with 2 custom fields attached to it... When I create a post of this type and fill in the custom fields, the data is, in fact, saved to the db... However, if I trash one of them, then that post's custom fields data is deleted from the database.

I thought trashing was just supposed to basically change the post_status to "trash" so it's out of view unless you actually delete it permanently?

If that's the case, why am I losing my custom fields data when I trash an item?

Here's all the relevant code for the above question:

<?php
add_action('admin_init', 'wpg_add_testimonial_author');
function wpg_add_testimonial_author() {
  add_meta_box('wpg_testimonial_author', __('Author Information', 'quotable'), 'wpg_testimonial_author', 'testimonials', 'side', 'low');
}

function wpg_testimonial_author() {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];
  ?>
  <p>
    <label><?php _e("Author's Name:", 'quotable'); ?></label>
    <input name="testimonial_author_name" value="<?php echo $testimonial_author_name; ?>" />
  </p>
  <p>
    <label><?php _e('Attribution Link:', 'quotable'); ?></label>
    <input name="testimonial_author_link" value="<?php echo $testimonial_author_link; ?>" />
  </p>
  <?php
}

function wpg_save_testimonial_author() {
  global $post;
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return $post_id;
  }
  if (defined('DOING_AJAX')) {
    return;
  }
  update_post_meta($post->ID, 'testimonial_author_name', $_POST['testimonial_author_name']);
  update_post_meta($post->ID, 'testimonial_author_link', $_POST['testimonial_author_link']);
}
add_action('save_post', 'wpg_save_testimonial_author');

function wpg_row_actions() {
  global $post;
  if($post->post_type == 'page') {
    if(!current_user_can('edit_page')) {
      return;
    }
  }
  else {
    if(!current_user_can('edit_post')) {
      return;
    }
  }
  if($post->post_status == 'trash') {
    $actionLinks  = '<div class="row-actions"><span class="untrash"><a title="'.__('Restore this item', 'quotable').'" href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=untrash', 'untrash-'.$post->post_type.'_'.$post->ID).'">'.__('Restore', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="trash"><a href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=delete', 'delete-'.$post->post_type.'_'.$post->ID).'" title="'.__('Delete this item permanently', 'quotable').'" class="submitdelete">'.__('Delete Permanently', 'quotable').'</a></span>';
  }
  else {
    $actionLinks  = '<div class="row-actions"><span class="edit"><a title="'.__('Edit this item', 'quotable').'" href="'.get_admin_url().'post.php?post='.$post->ID.'&action=edit">'.__('Edit', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="inline hide-if-no-js"><a title="'.__('Edit this item inline', 'quotable').'" class="editinline" href="#">'.__('Quick Edit', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="trash"><a href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=trash', 'trash-'.$post->post_type.'_'.$post->ID).'" title="'.__('Move this item to the Trash', 'quotable').'" class="submitdelete">'._x('Trash', 'verb (ie. trash this post)', 'quotable').'</a></span>';
  }
  return $actionLinks;
}

function wpg_edit_testimonials_columns($columns) {
  $columns = array(
    'cb' => '<input type="checkbox" />',
    'testimonial_author' => __('Author', 'quotable'),
    'testimonial_text' => __('Testimonial', 'quotable'),
    'attribution_link' => __('Attribution Link', 'quotable'),
    'date' => __('Date Added', 'quotable')
  );
  return $columns;
}

function wpg_manage_testimonials_columns($column, $post_id) {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];

  $wpg_row_actions  = wpg_row_actions();

  switch($column) {
    case 'testimonial_author':
      echo $testimonial_author_name.$wpg_row_actions;
    break;

    case 'testimonial_text':
      echo $post->post_content;
    break;

    case 'attribution_link':
      echo $testimonial_author_link;
    break;

    default :
      break;
    }
  }
  add_filter('manage_edit-testimonials_columns', 'wpg_edit_testimonials_columns');
  add_action('manage_testimonials_posts_custom_column', 'wpg_manage_testimonials_columns', 10, 2);

The custom post type doesn't support the "title" portion of posts, so it's not included as one of the columns in the edit posts page. Therefore, I had to hack my own version of the row_actions() function to enable the edit/quick edit/trash links when each post is hovered.

All of the functionality works as it should... Except that the "testimonial author" and "attribution link" values are deleted from the database when moving a post to the trash. No idea why...

Share Improve this question edited Oct 25, 2011 at 12:09 Nero_DCLXVI asked Oct 25, 2011 at 0:04 Nero_DCLXVINero_DCLXVI 2163 silver badges12 bronze badges 1
  • I've narrowed it down... I added yet ANOTHER post type with all the exact same attributes as this one, but I didn't include the custom function for adding the "trash" link. Instead I added the "title" as one of the array keys when setting up the custom columns... However, it still deletes the custom field data even when I trash the post using the original trash link. So this leads me to believe it's got to be something to do with my save method for the custom field data. I read somewhere that "save_post" is fired when trashing a post... Any way around this? – Nero_DCLXVI Commented Oct 25, 2011 at 3:30
Add a comment  | 

3 Answers 3

Reset to default 4

It seems that the action save_post gets fired when sending a post to the trash... Therefore, my custom metadata save function was being activated with no $_POST data to send thru it.

To circumvent this, I wound up adding a nonce to the save function.

function wpg_testimonial_author() {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];
  ?>
  <p>
    <label><?php _e("Author's Name:", 'quotable'); ?></label>
    <input name="testimonial_author_name" value="<?php echo $testimonial_author_name; ?>" />
  </p>
  <p>
    <label><?php _e('Attribution Link:', 'quotable'); ?></label>
    <input name="testimonial_author_link" value="<?php echo $testimonial_author_link; ?>" />
    <input type="hidden" name="testimonial_author_noncename" id="testimonial_author_noncename" value="<?php echo wp_create_nonce(plugin_basename(__FILE__).$post->ID); ?>" />
  </p>
  <?php
}

function wpg_save_testimonial_author($post_id) {
  global $post;
  if (!wp_verify_nonce($_POST['testimonial_author_noncename'], plugin_basename(__FILE__).$post->ID)) {
    return $post->ID;
  }
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return $post_id;
  }
  if(defined('DOING_AJAX')) {
    return;
  }
  if(!current_user_can('edit_post')) {
    return $post->ID;
  }
  if($post->post_type == 'revision') {
    return;
  }
  update_post_meta($post->ID, 'testimonial_author_name', $_POST['testimonial_author_name']);
  update_post_meta($post->ID, 'testimonial_author_link', $_POST['testimonial_author_link']);
}
add_action('save_post', 'wpg_save_testimonial_author');

Hopefully this might help someone else later...

I have run into the same problem and found even shorter solution (in terms of writing).

if (isset($_POST['action']) && $_POST['action'] == 'editpost') {
// do your update_post_meta, delete_post_meta, etc.
}

I tried to test it now on 5+ WP version and seems to fire only on editing or saving a new post.

Wow, thank you Nero_DCLXVI. Very helpful. For future people looking to implement this, here's simplified instructions of his solution:

  1. Add this hidden input along with your other custom meta inputs:
<input 
    type="hidden" \
    name="prevent_delete_meta_movetotrash" 
    id="prevent_delete_meta_movetotrash" 
    value="<?php 
        echo wp_create_nonce( plugin_basename(__FILE__) . $post->ID ); 
    ?>" />
  1. Add this right before your update_post_meta() functions.
if ( ! wp_verify_nonce( 
        $_POST['prevent_delete_meta_movetotrash'], 
        plugin_basename(__FILE__) . $post->ID ) 
    ) { 
    return $post_id; 
}
发布评论

评论列表(0)

  1. 暂无评论