I need help preventing a custom field from being updated after it's been published for the first time.

I have posts that has a link to an mp3 file and a description of the file. When it's published, I have a function that removes the link to the mp3 file from the content and adds it to a custom field called audio_url.

If I make changes to the post, the mp3 link in the custom field gets removed.

Code in my functions.php:

function save_url_link( $post_id, $post ){
if ( has_post_format('audio', $post_id)) {
if (! wp_is_post_revision( $post_id ) ){
  preg_match_all ( "/(http|https):\/\/.*\/(.*)\.(mp3|m4a|ogg|wav|wma)/", $post->post_content, $matches );
  update_post_meta( $post_id, 'audio_url', $matches[0][0] ); 
  remove_action('save_post', 'save_url_link', 10, 2);
  wp_update_post(array('ID' => $post_id, 'post_content' => preg_replace('/(http|https):\/\/.*\/(.*)\.(mp3|m4a|ogg|wav|wma)/', "", $post->post_content)));

1 Answer 1


You are updating the audio_url regardless of one was found in the content or not. Make it conditional:

if(preg_match_all ( "/(http|https):\/\/.*\/(.*)\.(mp3|m4a|ogg|wav|wma)/", $post->post_content, $matches )) {
    update_post_meta( $post_id, 'audio_url', $matches[0][0] ); 

In this case, you could also use preg_match, because you're only looking for a single instance.

Also make sure that your regex does work correctly. Right now, it would get you wrong results if two URLs are in the document, since ".*" is greedy and will match as much as possible. Add a ? to change that behaviour to non-greedyness. While we're at it, let's remove the need to escape every Slash by using different delimiters:


You don't really need the parentheses around that second .*?, but maybe you have more code that needs it? Also, (http|https) could be written as https?, the question mark makes the previous character optional.

  • Tried your example and did not work. Commented Oct 23, 2017 at 9:25
  • That's kind of vague. What exactly did you try? Is audio_url overwritten with an empty string or is the field removed from the DB completely? When you're editing the post after the initial save, do you see audio_url with the correct value under custom fields?
    – janh
    Commented Oct 23, 2017 at 9:28
  • Found a solution: if (get_post_meta( $post_id, 'audio_url', true ) == '') { update_post_meta( $post_id, 'audio_url', $matches[0][0] ); } Commented Oct 23, 2017 at 9:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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