Check for duplicated post meta values

Some background

For a couple of months, I’m using WordPress as an application framework and this requires some additional validations on post meta fields, one of those validations is the need to have unique meta values, for some post types. For instance a phone number on a “client record” each client has one number and if you’re inserting a new client with the same number, something went wrong and you need to review that record.

To allow this validation, I’ve used the “publish_post” hook and checked for the field value in the posts from that post type.

If the value already exists in other post meta, the post is set to “Draft” and the user informed of the duplicated value in order to correct it.

Check for duplicated post_meta values

add_action('publish_{your_post_type}','rfvc_check_duplicate_{your_post_type}', 10, 2);

function rfvc_check_duplicate_{your_post_type}( $post_id, $post ){
        
        global $wpdb;
        $meta_key = {your_meta_key}

        //Check if publishing {your_post_type} and not auto saving 
	if( get_post_type( $post_id ) != {post_type} ) return;
	if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;

	//Get unique meta value if meta_value already defined
	$unique_meta = get_post_meta( $post_id, $meta_key , true );
        
        //Get unique meta value if new
	if( isset($_POST) && $unique_meta != $_POST[$meta_key] ){
		$unique_meta = $_POST[$meta_key];
        }

        $duplicated_entries = $wpdb->get_results( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key LIKE {$meta_key} AND meta_value = {$unique_meta} " );
        
        if( 0 != count($duplicated_entries) && $post_id != $duplicated_entries[0]->post_id ){

		//Add Error Message
		add_settings_error(
		    'duplicated-meta',
		    'duplicated-meta',
		    __('
<style>#message{ display: none; }</style>

Duplicated Field. <strong>Post saved as Draft</strong>.','rfvc'),
		    'error'
		);
		    
		set_transient( 'settings_errors', get_settings_errors(), 30 );

		$post_data = array(
			'ID'           => $post_id,
			'post_status' => 'draft'
		);
		wp_update_post( $post_data );

	}

       return;

}