I'm developing a plugin, in which the administrator has the ability to add and remove ZIP codes on the backend. I found that the best way to do this is by creating a custom post type named zip_code with only a title being supported , as that functionality is already built-in to Wordpress.

What I'm having trouble with is validating the title, as it must be a valid ZIP code to avoid errors on the front end.

I've added the following action hooks:

    // Action hook to intercept Wordpress' default post saving function and redirect to ours
    add_action('save_post', 'zip_code_save');

    $validator = new Validator();
    // Called after the redirect
    add_action('admin_head-post.php', array($validator, 'add_plugin_notice'));

zip_code_save function:

public function zip_code_save() {

    global $post;

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    if (isset($_POST['post_type']) && $_POST['post_type'] == 'zip_code') {

        $validator = new Validator();

        if (!$validator->validate(get_the_title($post->ID))) {

            return false;
        } else {
                'zip_code', get_the_title($post->ID));


And finally this is my Validator class:

class Validator { 
    //This for your your admin_notices hook
    function show_error() {
        echo '<div class="error">
       <p>The ZIP Code entered is not valid. <b>Note</b>: only US ZIP codes are accepted.</p>

    //update option when admin_notices is needed or not
    function update_option($val) {
        update_option('display_my_admin_message', $val);

    //function to use for your admin notice
    function add_plugin_notice() {
        if (get_option('display_my_admin_message') == 1) {
            // check whether to display the message
            add_action('admin_notices', array(&$this, 'show_error'));
            // turn off the message
            update_option('display_my_admin_message', 0);

    function validate($input) {

        $zip = (isset($input) && !empty($input)) ? sanitize_text_field($input) : '';

        if ( !preg_match( '/(^\d{5}$)|(^\d{5}-\d{4}$)/', $zip  ) ) {
            return false;
        } else {
            return true;



The above code successfully outputs an error message if the entered ZIP is not valid, however regardless of the error, it does publish the post. Is there a way to block the publishing of the post if the title is not valid?

Also, is there a way to prevent WP of creating drafts automatically? Since there is so little data, it's really irrelevant here, and more a hassle.

1 Answer 1


Whether a post is a draft or published is defined by the post status, not any of the meta fields, so you'll have to hook into wp_insert_post_data and force the post_status to draft if anything in your form is invalid:

add_filter( 'wp_insert_post_data', function( $data ) {
    if ( $data['post_type'] != 'zip_code' )
        return $data;

    // Validate your nonces and $_POST fields here
    if ( ! $valid ) {
        $data['post_status'] = 'draft'; // Force draft

Also note that wp_insert_post_data runs before save_post, so you'll have to validate again and save the meta fields in save_post just like you're already doing.

I would also recommend not using options for admin notice triggers. They're global for all users, and they're autoloaded by default every time and everywhere. Use the usermeta table instead by using set_user_setting() and then get_user_setting().

Hope that helps!

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.