I have a custom post type with several custom fields. I am looking to do some validation on these fields because they will be used downstream by other services. So, it is important that it can't be saved until it is correctly entered. The validation is reasonably complex and requires custom logic.

Unfortunately, it also won't work to use a plugin in this particular case.

Is there an ideal hook to use in this case? At a high level -- whats the best way to go about this.

  • You mean plugin in the sense to do it with some pre-made plugin instead of a hand-coded solution? -- Where do you have code at the moment, any details so far about what you already do? – hakre Feb 8 '11 at 23:43
  • @hakre: I would like to integrate it with the other code that I have already written to draw the custom metaboxes with the fields. I am not opposed to plug-ins in general -- I just don't think it work for this case. Code right now is fairly simple and is setup with hooks in my functions.php file. I add my metaboxes with the custom fields. I remove almost all default metaboxes. Not really looking for an answer that codes it all out for me. Just looking for the high level: if I had to do it, I would do it like this type answer. – Ethan Seifert Feb 9 '11 at 0:10
  • Okay, I asked because I think first of all you need to build your set of validation functions. Normally those just return true or false regarding the data they check. So part of the solution is to think about where to store those functions. – hakre Feb 9 '11 at 0:39

Example code in add_meta_box() documentation uses save_post hook (at the very end of wp_insert_post() function) to add custom fields data from metabox.

You must be using something like that already in your metaboxes, is it not appropriate place to validate your data?..

  • I don't see why not. I will go ahead and do that. – Ethan Seifert Feb 9 '11 at 17:35

(Taken from my answer to a similar question posted here)

There are two steps to this method: first, a function to save your custom metabox field data (hooked to save_post), and second, a function to read that new post_meta (which you just saved), validate it, and modify the result of saving as necessary (also hooked to save_post, but after the first). The validator function, if validation fails, actually changes the post_status right back to "pending", effectively preventing the post from being published.

Since the save_post function gets called a lot, each function has checks to only execute when the user means to publish, and only for your custom post type (mycustomtype).

I also typically add some custom notice messages to help the user know why their post didn't publish, but those got a bit complicated to include here...

add_action('save_post', 'save_my_fields', 10, 2);
add_action('save_post', 'completion_validator', 20, 2);

function save_my_fields($pid, $post) {
    // don't do on autosave or when new posts are first created
    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
    // abort if not my custom type
    if ( $post->post_type != 'mycustomtype' ) return $pid;

    // save post_meta with contents of custom field
    update_post_meta($pid, 'mymetafield', $_POST['mymetafield']);

function completion_validator($pid, $post) {
    // don't do on autosave or when new posts are first created
    if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
    // abort if not my custom type
    if ( $post->post_type != 'mycustomtype' ) return $pid;

    // init completion marker (add more as needed)
    $meta_missing = false;

    // retrieve meta to be validated
    $mymeta = get_post_meta( $pid, 'mymetafield', true );
    // just checking it's not empty - you could do other tests...
    if ( empty( $mymeta ) ) {
        $meta_missing = true;

    // on attempting to publish - check for completion and intervene if necessary
    if ( ( isset( $_POST['publish'] ) || isset( $_POST['save'] ) ) && $_POST['post_status'] == 'publish' ) {
        //  don't allow publishing while any of these are incomplete
        if ( $meta_missing ) {
            global $wpdb;
            $wpdb->update( $wpdb->posts, array( 'post_status' => 'pending' ), array( 'ID' => $pid ) );
            // filter the query URL to change the published message
            add_filter( 'redirect_post_location', create_function( '$location','return add_query_arg("message", "4", $location);' ) );

For multiple metabox fields, just add more completion markers and retrieve more post_meta and do more tests..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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