WordPress Custom Field Should be Unique. Is it possible?

You can use the filter hooks 'add_post_metadata' and 'update_post_meta', when a function hooked there return anything but NULL the process of adding/updating metadata is stopped.

The two hooks passes almost same args:

  1. NULL
  2. post id
  3. the meta key
  4. the meta value being added/updated

Only last argument is different, in case of update is previous value, in case of add is the $unique value passed to add_post_meta.

The idea is:

  1. run a filter callback for both hooks
  2. use a custom SQL query to be sure the value is unique
  3. id the value is already used, then return anything but NULL

Example:

add_filter( 'add_post_metadata', 'my_unique_url_meta', 10, 4 ); 
add_filter( 'update_post_metadata', 'my_unique_url_meta', 10, 4 );

function my_unique_url_meta( $null, $pid, $key, $value ) {
  // here I assume the meta key to force unique is "url", change this to fit your needs
  if ( $key !== 'url' ) return $null;
  global $wpdb;
  $exists = $wpdb->get_col( $wpdb->prepare(
    "SELECT meta_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s",
    $key, $value
  ) );
  // return anything but NULL stop the process, however returning FALSE is the only way
  // to obtain a "pretty" error message by WordPress in post admin screen
  if ( ! empty( $exists ) ) return FALSE;
}

Using previous code, when the meta field for the meta key already exits, you obtain an error message like “Please provide a custom field value.” just like you haven’t provided any custom field value, and I’m afraid that message can’t be changed.
In addition, if after added an already used meta value for the custom field, you straight save/update the post (before click on “Add Custom Field” button inside the metabox) than you’ll see no error message, but when the page is reloaded the custom field is just not there.

Previuos warning only apply to core “Custom Fields” metabox, but you can use a custom metabox for your unique metakey and use ajax to show a proper error message, however, my code assure no one can add a non-unique meta value even using code (and not UI).