Tell me more ×
WordPress Answers is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a custom post type with about 20 different metaboxes. What I would like to do is be able to hit "New post" for this type, enter the post title, fill in an unique identifier on one of the metafields (like a Freebase ID), and then go out and query Freebase, automatically bringing in the data for the other 19 metas.

The going out and getting data works just fine, and when I tested it using different meta keys, it works like a charm. But when I use update_post_meta to set the values to the proper keys (ie the ones actually used by my metaboxes), the metadata gets overwritten by the empty metaboxes in the Edit Post form.

I had been hooking the function that gets the external metadata into save_post. Is there a better method? Better place to hook into? Is there an action somewhere between saving the data from the form and the redirect to the edit page where I could perform the update_post_meta function?

Thanks in advance.

UPDATE: Here's the code - shortened, as I figured showing four of the metas was sufficient.

Again, this code works perfectly IF I save the metadata to keys not being used by the theme (ie if I append the word "Test" to each metakey below, it works fine. That's why I'm assuming the metas are being overwritten by the blank meta boxes in the post edit form.)

<?php
function get_album_data($post_id) {
// after the user fills in the Title and ID and hits "Save Draft"
// this function goes out and gets every piece of information available about this album
global $wpdb;
$slug = 'album';

// check whether anything should be done 
$_POST += array("{$slug}_edit_nonce" => '');
if ( $slug != $_POST['post_type'] ) {
    return;
}
if ( !current_user_can( 'publish_posts', $post_id ) ) {
    return;
}
// set a flag so this only runs once
$initial_data_imported = get_post_meta($post_id, 'initial_data_imported', $single);
if ( !empty( $initial_data_imported ) ) {
    return;
}

/* Request passes all checks; update the post's metadata */
if (isset($_REQUEST['Album_ID'])) {
    $album_id = $_REQUEST['Album_ID'];

    // curl request info goes here

    $album_artist = $search_results->album->artist;
    $album_producer = $search_results->album->producer;
    $album_label = $search_results->album->label;
    update_post_meta ($post_id, 'Artist', $album_artist);
    update_post_meta ($post_id, 'Producer', $album_producer);
    update_post_meta ($post_id, 'Label', $album_label);
    update_post_meta( $post_id, 'initial_data_imported', true );
    }
}

add_action( 'save_post', 'get_album_data' );
?>
share|improve this question
Would pre_get_posts work here? Or maybe add_meta_boxes? – Neil Jun 27 '12 at 18:25
Could we see some code? – Stephen Harris Jun 27 '12 at 18:48
Is the example missing some code? I don't see the $search_results object defined in this scope, so as-is it makes sense that those values are empty. (See lines 28,29 and 30 of the supplied code.) – MathSmath Jun 27 '12 at 20:40
Again, @MathSmath, the code above isn't "as is". It's edited to take out the portions that were irrelevant to the question. The curl request and the data parsing run flawlessly. The problem I'm trying to avoid is having my meta fields overwritten by the empty boxes in the Edit Post form. There are about 20-30 lines of code I blew out to paste it here and simply replaced it with "// curl request info goes here" – Neil Jun 27 '12 at 20:43
Since these values are being added programatically, is my best bet to use remove_meta_box to remove the boxes from the Edit Form? Or is there some other way? – Neil Jun 27 '12 at 21:41
show 6 more comments

closed as too localized by toscho May 15 at 19:08

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, see the FAQ.

2 Answers

It turns out my theme had a function hooked into save_post that was overwriting the metadata with blank fields, because there was no text in the input boxes:

add_action( 'save_post', 'album_meta_save' );
function album_meta_save( $id )
{
    // do stuff, including overwrite the custom fields with update_post_meta
}

So I ended up doing the following in a child theme:

function my_undo_hooks( ) {
    remove_action( 'save_post', 'album_meta_save' );
}
add_action( 'after_setup_theme', 'my_undo_hooks' );
add_action( 'save_post', 'my_album_meta_save' );
function my_album_meta_save( $id )
{
    // duplicate the parent theme's function, MINUS the overwriting of the custom fields
}

Now it works just fine. Thanks for the questions and comments - it helped me search out the right answer.

share|improve this answer

If I understand correctly, the theme you have has metaboxes built in for your album post type, and the theme handles saving the post meta contained in these boxes. However, you would like to use one field to auto-populate the rest of the meta.

(Note: you seem to be using the terms Custom Field and metaboxes interchangeably. They are different. I'm assuming that you using metaboxes.).

The set up you have should work. But your save_post callback is (probably) being called before the theme's. Thus you update the post meta with the remotely retrieved data, but then afterwards the theme updates the post meta with data it received from the form (i.e. an empty string).

The trick is to ensure your callback is called after theme's. The priority for the theme's callback is probably the default - 10. But you can't be sure unless you inspect the code. Try setting your callback's priority to 20:

add_action( 'save_post', 'get_album_data', 20 );

Other things I should point out:

  • Prefix your function names with something unique e.g.: wpse56728_get_album_data. This reduces the risk of name clash
  • Check that the passed post isn't a revision: wp_is_post_revision($post_id) and just return from your function early if it is.
  • Ideally you should check the metabox's nonce (it should have one) prior to processing.
  • Don't use curl. See this on HTTP requests with WordPress.
share|improve this answer
Thank you. You've started to help me make sense of this. After some digging, I found that my theme's functions.php contains a "meta_save" function that hooks into save_post and appears to be overwriting my data. The whole point behind me writing this as a plugin was to avoid hacking the theme; the trouble becomes that if I'm understanding everything correctly, my plugin is loading before the theme files, and a child theme would just load before the parent's functions.php, so I'm not even sure where to call a remove_action to get rid of the meta_save. – Neil Jun 28 '12 at 1:12
And you're right, I guess I have been using "Custom Field" and "metaboxes" interchangably. In the example I'm using, "Artist", "Producer" and "Label" would be custom fields in a metabox specific to the "Album" post type. And the Album ID is ALSO a custom field in the same metabox. – Neil Jun 28 '12 at 1:13
Additionally, I tried saving my callback's priority to 1000, just to be sure. Same result. – Neil Jun 28 '12 at 2:10
your answer was part of what pointed me in the right direction. I'm posting the answer I ended up finding below. – Neil Jun 28 '12 at 16:43

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