Validating post title and content in WordPress

I intend to let users create blog posts via the front end. I need to make sure the post title and content are each less than 100 characters.

Which hook should I hook my validation function to?

Read More

Thanks in advance.

Related posts

Leave a Reply

3 comments

  1. This code makes sure that post title is not empty or longer than 100 characters. You can adjust it to your needs if necessary. The code will work as follows:

    • If errors occur while you are creating a new post, the post won’t be published and it will remain in auto-draft status (it won’t show in the listing);
    • If errors occur during the update of the existing post, the post_title and post_status will not be changed;
    • Replace your_custom_post_type with your custom post type.

    The code:

    <?php
    
    add_action('save_post_{your_custom_post_type}', 'custom_validate_post', 10, 2);
    
    if (!function_exists('custom_validate_post')) {
        function custom_validate_post(int $post_ID, WP_Post $post): void
        {
            // Exit early if save_post is triggered when trashing the post
            if ($post->post_status === 'trash' || defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
                return;
            }
    
            $errors = [];
    
            // Validation filters
            if (empty($post->post_title)) {
                $errors['title'] = 'The title is required';
            }
    
            if(strlen($post->post_title) > 100) {
                $errors['title'] = 'The title should not be longer than 100 characters';
            }
    
            // If we have errors lets setup some messages
            if (!empty($errors)) {
                // Save the errors as option
                update_option('post_errors', $errors);
    
                // admin_notice is create by a $_GET['message'] with a number that wordpress uses to
                // Display the admin message so we will add a filter for replacing default admin message with a redirect
                add_filter('redirect_post_location', function (string $location) {
                    // Remove $_GET['message']
                    $location = remove_query_arg( 'message', $location );
    
                    // Add our new query sting
                    $location = add_query_arg( 'custom_validation', 'failed', $location );
    
                    // Return the location query string
                    return $location;
                });
            }
        }
    }
    
    // We use this action to get the data before and after the update in order to revert the data if validation fails
    add_action('post_updated', 'custom_set_old_post_data_if_error', 10, 3);
    
    if (!function_exists('custom_set_old_post_data_if_error')) {
        function custom_set_old_post_data_if_error(int $post_ID, WP_Post $post_after, WP_Post $post_before)
        {
            // Exit early if post_updated is triggered when trashing the post
            if ($post_after->post_status === 'trash' || $post_after->post_type !== 'your_custom_post_type') {
                return;
            }
    
            if (empty($post_after->post_title) || strlen($post_after->post_title) > 100) {
                // We must remove this action or it will loop forever since we use wp_update_post below
                remove_action('post_updated', 'custom_set_old_post_data_if_error');
    
    
                // Set old `post_title` and `post_status` if validation fails
                wp_update_post(
                    [
                        'ID' => $post_after->ID,
                        'post_title' => $post_before->post_title,
                        'post_status' => $post_before->post_status,
                    ]
                );
    
                add_action('post_updated', 'custom_set_old_post_data_if_error');
            }
        }
    }
    
    // Add new admin message
    add_action( 'admin_notices', function () {
            if (isset($_GET['custom_validation']) && $_GET['custom_validation'] === 'failed') {
    
            // Get the errors from the option album_errors
            $errors = get_option('post_errors');
    
            // Now delete the option post errors
            delete_option('post_errors');
    
            $display = '<div id="notice" class="error"><ul>';
    
            // Because we are storing as an array we should loop through them
            foreach ( $errors as $error ) {
                $display .= '<li>' . $error . '</li>';
            }
    
            $display .= '</ul></div>';
    
            // Finally echo out our display
            echo $display;
    
            // Add some jQuery
            ?>
            <script>
                jQuery(function($) {
                    $("#title").css({"border": "1px solid red"})
                });
            </script>
            <?php
        }
    });
    

    There are couple of things to be aware of:

    • if there are posts in trash with the title that is not valid, you won’t be able to untrash these posts before changing the title;
    • if you want to apply this to all of the posts and not a certain custom post type, use save_post hook instead of save_post_{your_custom_post_type} and remove $post_after->post_type !== 'your_custom_post_type' condition from the code.

    Wish you best of luck!

  2. Try this:

    Use plugin for that. It will help you needful.

    Refer this: http://wordpress.org/plugins/post-title-validation/

    OR

    Use this code.

    add_action( 'admin_notices', 'custom_error_notice' );
    function custom_error_notice(){
        global $current_screen, $post;
        if ( $current_screen->parent_base == 'edit' ){
            if((!$post->post_name && !$post_content) && $_GET['post']) {
                wp_redirect(admin_url('post-new.php?empty=1'));
            }
            if($_GET['empty']) echo '<div class="error"><p>Warning - Please fill up all fields correctly!</p></div>';
        }
    }
    
    • Thanks