Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a custom post type which is working fine, however the meta box does isn't saving.

Long & short, i'm stumped!

add_action('init', 'portfolio');
function portfolio() {
 $args = array(
  'label' => __('Portfolio'),
  'singular_label' => __('Portfolio'),
  'public' => true,
  'show_ui' => true,
  'menu_position' => 5,
  'capability_type' => 'page',
  'hierarchical' => false,
  'rewrite' => true,
  'show_in_nav_menus' => true,
  'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
  'has_archive' => true
 );

 register_taxonomy( 'type', 'portfolio',
  array(
             'hierarchical' => false,
    'label' => __('Project Type'),
    'query_var' => 'type',
    'rewrite' => array('slug' => 'portfolio/type' )
  )
 );

 register_post_type( 'portfolio' , $args );
}

add_action("admin_init", "admin_init");
add_action('save_post', 'save_meta_data');

function admin_init(){
add_meta_box("portfolio_text", "Main Text", "portfolio_options", "portfolio", "normal", "high");
}

/* Meta Values for Shorts */
function portfolio_options() {
 global $post;
 $custom = get_post_custom($post->ID);
 $short_embed = $custom["portfolio_text"][0]; ?>
 <textarea name="portfolio_text" cols="40" rows="1" style="width:98%; height:100px"/><?php echo get_option('portfolio_text'); ?></textarea> 
<?php }


/* Save Changes */
function save_meta_data($ID = false, $post = false) {
    if($post->post_type != 'portfolio')
        return;
    update_post_meta($ID, 'portfolio_text', $_POST['portfolio_text']);
}

Your help is appreciated!

Cheers, George

share|improve this question
    
Paste your save_meta_data function so we can see –  Bainternet Jan 22 '11 at 22:37
    
do you mean, function save_meta_data($ID = false, $post = false) { if($post->post_type != 'portfolio') return; update_post_meta($ID, 'portfolio_text', $_POST['portfolio_text']); } –  George Wiscombe Jan 22 '11 at 22:42
    
I mean the function that acutely saves the meta data, that could it. –  Bainternet Jan 22 '11 at 23:23

2 Answers 2

up vote 3 down vote accepted

Hi @George Wiscombe:

So close, yet so far! (I know the pain, I'm there often. :) You almost had it but are using the wrong hook to do the post meta update. Use the 'wp_insert_post_data' hook instead of the 'save_post' hook:

<?php
if (!class_exists('YourSite_Portfolio')) {
  class YourSite_Portfolio {
    static function on_load() {
      add_action('init',array(__CLASS__,'init'));
      add_action("admin_init",array(__CLASS__,'admin_init'));
      add_action('wp_insert_post_data',array(__CLASS__,'wp_insert_post_data'),10,2);
    }
    static function init() {
      register_post_type( 'portfolio',array(
        'label' => __('Portfolio'),
        'singular_label' => __('Portfolio'),
        'public' => true,
        'show_ui' => true,
        'menu_position' => 5,
        'capability_type' => 'page',
        'hierarchical' => false,
        'rewrite' => true,
        'show_in_nav_menus' => true,
        'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
        'has_archive' => true
      ));
      register_taxonomy( 'type', 'portfolio', array(
        'hierarchical' => false,
        'label' => __('Project Type'),
        'query_var' => 'type',
        'rewrite' => array('slug' => 'portfolio/type' )
      ));
    }
    static function admin_init(){
      add_meta_box('portfolio_text','Main Text',array(__CLASS__,'portfolio_options'),'portfolio','normal','high');
    }
    static function portfolio_options($post,$metabox) {
      $portfolio_text =  get_post_meta($post->ID,'portfolio_text',true);
    $html =<<<HTML
<textarea name="portfolio_text" cols="40" rows="1" style="width:98%; height:100px"/>{$portfolio_text}</textarea>
HTML;
      echo $html;
    }
    static function wp_insert_post_data($data,$postarr) {
      if ($postarr['post_type'] == 'portfolio') {
        update_post_meta($postarr['ID'], 'portfolio_text', $postarr['portfolio_text']);
      }
      return $data;
    }
  }
  YourSite_Portfolio::on_load();
}

The 'wp_insert_post_data' hook is where WordPress captures the values from the $_POST array; by the time you reach 'save_post' WordPress has reloaded the post and that's why 'portfolio_text' empty when you are trying to save it.

share|improve this answer
    
Hi Mike, Thanks for your feedback. I swapped out my save action/function for yours however I'm still getting the same problem. Any ideas? –  George Wiscombe Jan 23 '11 at 1:23
    
Hi @George Wiscombe - I was clearly brainfried when I posted that, sorry. I've updated it and I've rewritten it to use a class to encapsulate everything to minimize the likelihood of it conflicting with a (badly written) plugin you might use. Since you were using function names like admin_init() and save_meta_data() in the global function namespace it's likely those would conflict with someone else's plugin code (or even future code from WordPress) so what I've done pretty much eliminates that concern. –  MikeSchinkel Jan 23 '11 at 3:26
    
Brilliant, thanks Mike! This is perfect. If you have another couple of minutes, could you show me an example that would have 2+ custom fields. (I'm just trying to understand it as opposed to copy&paste) –  George Wiscombe Jan 23 '11 at 12:10
    
@George Wiscombe - Glad I could help. Just add fields in your portfolio_options() and wp_insert_post_data() functions. Very straightforward. –  MikeSchinkel Jan 23 '11 at 12:27
    
Great thanks, actually after a bit more testing i've found a problem. It now doesn't save the content of the default WP text-area, any ideas? –  George Wiscombe Jan 23 '11 at 12:28

the problem is with your portfolio_options function in this line:

<textarea name="portfolio_text" cols="40" rows="1" style="width:98%; height:100px"/><?php echo get_option('portfolio_text');** ?></textarea> 

its being saved and have been before but you are not calling it the right way, you are using get_option('portfolio_text') and that's not right because it not an option is a post metadata

so change get_option('portfolio_text') to get_post_meta($post->ID, 'portfolio_text', true);

so your function will look like this:

/* Meta Values for Shorts */
function portfolio_options() {
 global $post;
 $custom = get_post_custom($post->ID);
 $short_embed = $custom["portfolio_text"][0]; ?>
 <textarea name="portfolio_text" cols="40" rows="1" style="width:98%; height:100px"/><?php echo get_post_meta($post->ID, 'portfolio_text', true); ?></textarea> 
<?php }

that should do it!

share|improve this answer
    
@בניית אתרי - Good catch on the get_option(); I missed that part when eyeballing it. +1. –  MikeSchinkel Jan 23 '11 at 3:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.