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'm trying to set up a custom post type following this tutorial. However, I'm a bit confused as how/where to implement update_post_meta(). The tutorial suggests this pattern:

add_action('save_post', 'save_my_metadata');

function save_my_metadata()
{
    global $post;
    update_post_meta($post->ID, 'my_metadata', $_POST['my_metadata']);
}

Which does work, but has the unfortunate effect of adding that metadata to each and every post, whether it belongs to this custom type or not.

I've put the above in functions.php and am guessing that might be part of the problem. I'm guessing I need to restrict the 'save_post' action to only trigger for posts of my custom type.

share|improve this question
    
Nice question Bobby Jack but can I ask you to retitled the question to something like "How to Only Save Metadata for Specific Custom Post Types"; as is your title is too generic for people to recognize when they are looking for a solution to this problem. –  MikeSchinkel Aug 17 '10 at 20:14
    
@Mike: done (totally agree with your suggestion, thanks!) –  Bobby Jack Aug 18 '10 at 11:38

6 Answers 6

up vote 13 down vote accepted
function save_my_metadata($ID = false, $post = false)
{
    if($post->post_type != 'your_post_type')
        return;
    update_post_meta($ID, 'my_metadata', $_POST['my_metadata']);
}

That should work. Just replace 'your_post_type' with the name of the post type. Also, little known fact: the 'save_post' hook passes the post's ID as an argument.

EDIT

I updated the function to reflect Jan's comment. Thanks Jan!

share|improve this answer
1  
It even adds the post itself as the second argument, so you don't need to use the global variable. –  Jan Fabry Aug 17 '10 at 14:20
    
This solution does work ... I've used it on client projects before with a lot of success. –  EAMann Aug 17 '10 at 14:36
    
Brilliant- works like a charm. And I'm assuming that it would make sense to do "if ($post->post_type == 'animal') { update_post_meta($ID, "number_of_legs", $_POST['number_of_legs']); } else if ($post->post_type == 'vehicle') { update_post_meta($ID, "number_of_wheels", $_POST['number_of_wheels']); } // ... etc ... to handle several different post types? (Apologies for the poor formatting capabilities of comments!) –  Bobby Jack Aug 17 '10 at 14:38
    
Actually, with multiple post-types, I'd recommend using a switch statement instead. Less markup, faster performance, easier to add cases in the future. –  EAMann Aug 17 '10 at 14:43
    
@EAMann - yup, halfway through writing that, I realised a switch would be better, but comments aren't the ideal place to start editing code, so I got lazy ;) –  Bobby Jack Aug 17 '10 at 14:50

I cant get this to work - not sure what Im doing wrong - but Im trying to use post_updated hook instead of the save_post - as I want these values to be inserted after the post has been updated so I can retrieve values from the other custom fields.

 function update_meta ($ID = false, $post = false) {
  update_post_meta($ID, 'rest_long', 'Test 1');
  update_post_meta($ID, 'rest_lat', 'Test 2');
}

add_action('post_updated', 'update_meta');
share|improve this answer
    
Nevermind - I figured it out! –  jrutter Apr 10 '11 at 15:19

Personally, I prefer to follow the below pattern for adding custom meta handlers to post types. With the below, you can add the meta support to a post type by just adding the supports key ('subtitle' in the example below) to the supports array for the post type by calling add_post_type_support('my_post_type', 'subtitle');

class Subtitle_Meta_Handler {
    public function initialize() {
        add_action('add_meta_boxes', array($this, 'add_metabox'), 10, 2);
        add_action('save_post', array($this, 'update'));
    }

    public function add_metabox($post_type, $post)
    {
        if(post_type_supports($post_type, 'subtitle'))
        {
            add_meta_box('subtitle', 'Subtitle', array($this, 'metabox'), $post_type);
        }
    }

    public function metabox($post)
    {
        $subtitle = get_post_meta($post->ID, 'subtitle', true);
        if(!$subtitle)
        {
            $subtitle = '';
        }
        ?>
        <input type="text" style="width: 70%;" value="<?php echo esc_attr($subtitle);?>" name="subtitle" id="subtitle">
        <?php
        wp_nonce_field('update_subtitle', 'subtitle_nonce');
    }

    public function update($post_id)
    {
        if(wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
            return $post_id;
        }
        if(isset($_REQUEST['subtitle_nonce']) && wp_verify_nonce($_REQUEST['subtitle_nonce'], 'update_subtitle')) {
            $subtitle = trim(strip_tags($_REQUEST['subtitle'], '<b><strong><span><a>'));
            if(empty($subtitle)) {
                delete_post_meta($post_id, 'subtitle');
            } else {
                update_post_meta($post_id, 'subtitle', $subtitle);
            }
        }
    }
}
add_action('init', array(new Subtitle_Meta_Handler(), 'initialize'));

Hopefully something like this will soon be added into core.

share|improve this answer

@John P Bloch and @EAMann have already given great answers so mine is in addition:

  1. Consider prefixing your meta_keys with an underscore. Doing so hides them from the list of custom fields displayed on a post edit screen, i.e.

    function save_my_metadata($post_id,$post=false) {
       if($post->post_type=='your_post_type')
          update_post_meta($post_id, '_my_metadata', $_POST['my_metadata']);
    }
    
    Obviously that means you'd need a custom metabox to be able to edit the fields too. Here's an edit screen for context:



  2. Another thing you could do is add your own hook to make saving specific post types easier, i.e. your hook could be "save_{$post_type}_post"; for a movie post type it would be save_movie_post. Here's what you'd have to add to your theme's functions.php file or in a plugin somewhere:

    add_action('save_post', 'save_custom_post_type_posts',10,2);
    function save_custom_post_type_posts($post_id,$post=false) {
       do_action("save_{$post->post_type}_post");
    }
    
    With that you could then rewrite your original code like so (including the underscore trick from #1 above):

    add_action('save_my_postype_post','save_my_postype_metadata',10,2);
    function save_my_postype_metadata($post_id,$post) {
        update_post_meta($post_id, '_my_metadata', $_POST['my_metadata']);
    }
share|improve this answer

If you want to handle multiple post types, I'd recommend a basic switch statement:

add_action('save_post', 'save_my_metadata');

function save_my_metadata($ID = false, $post = false)
{
    switch($post->post_type) 
    {
        case 'post_type_1':
            // Do stuff for post type 1
            update_post_meta($ID, 'my_metadata', $_POST['my_metadata']); // Example...
            break;
        case 'post_type_2':
            // Do stuff for post type 2
            break;
        default:
            return;
    }
}

The cases are basically the same as if($post->post_type) == 'post_type_1') {} But don't require multiple if-else blocks. The default block in the switch handles cases where the post type isn't in your custom set.

share|improve this answer

Prior updating check whether or not the current post is of your post-type. That would ensure you don't save it for all posts.

You should check for the input as well (that's missing in your example) and next to that, keep in mind that you might only add the action when that post-type is active. If that's the case, you do not need to check for that post-type later on.

Getting a posts type: get_post_type() or $post->post_type;

share|improve this answer

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.