The challenge: Have an image URL, want its ID in the WordPress database
While working on new ideas for my plugin Quick Featured Images I had the need to get the ID of an uploaded image by its URL found in the post content.
To my surprise there was not such a built-in function in WordPress. So I finished a function which does this task. It has several properties:
- it tries to get the base file name of the image
- of any size (full, medium, thumbnail, custom size etc.)
- while ignoring image URLs to external servers and
- ignoring any query string in the image’s URL and
- looks up the new image URL in the database as post’s “Globally Unique Identifier” (column name: „guid“) and
- returns the corresponding ID as integer
- otherwise returns 0 (zero) to say „no such image“.
The solution
Here is the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /** * Takes an URL of an uploaded image * and returns its post id, else 0 * */ function get_image_id_by_url ( $url ) { global $wpdb; $img_id = 0; /* get_site_url(): look for internal images only, i.e. images from the media library and no image embedded by URL from external servers */ /* ([^/]+)\.[a-z0-9]+$: get the base file name without any file extension */ preg_match( '|' . get_site_url() . '|i', $url, $matches ); // if site-owned image if ( isset( $matches ) and 0 < count( $matches ) ) { // delete optional query string $url = preg_replace( '/([^?]+).*/', '\1', $url ); /* delete image dimensions informations, just take base name and extension */ $guid = preg_replace( '/(.+)-\d+x\d+\.(\w+)/', '\1.\2', $url ); // look up its ID in the db $img_id = $wpdb->get_var( $wpdb->prepare( "SELECT `ID` FROM $wpdb->posts WHERE `guid` = '%s'", $guid ) ); /* if it is not 0, false or null: cast it to integer */ if ( $img_id ) { // finally we have an id $img_id = intval( $img_id ); } } // if $matches return $img_id; } |
/** * Takes an URL of an uploaded image * and returns its post id, else 0 * */ function get_image_id_by_url ( $url ) { global $wpdb; $img_id = 0; /* get_site_url(): look for internal images only, i.e. images from the media library and no image embedded by URL from external servers */ /* ([^/]+)\.[a-z0-9]+$: get the base file name without any file extension */ preg_match( '|' . get_site_url() . '|i', $url, $matches ); // if site-owned image if ( isset( $matches ) and 0 < count( $matches ) ) { // delete optional query string $url = preg_replace( '/([^?]+).*/', '\1', $url ); /* delete image dimensions informations, just take base name and extension */ $guid = preg_replace( '/(.+)-\d+x\d+\.(\w+)/', '\1.\2', $url ); // look up its ID in the db $img_id = $wpdb->get_var( $wpdb->prepare( "SELECT `ID` FROM $wpdb->posts WHERE `guid` = '%s'", $guid ) ); /* if it is not 0, false or null: cast it to integer */ if ( $img_id ) { // finally we have an id $img_id = intval( $img_id ); } } // if $matches return $img_id; }
Examples of usage
To use the function just take this line:
1 | $id = get_image_id_by_url( $some_url ); |
$id = get_image_id_by_url( $some_url );
To check whether the returned value is a valid ID, just remember that the function returns a positive integer or the 0. If it returns 0 there was no image found.
The 0 has the same boolean value as ‚false‘.
A positive integer has the same boolean value as ‚true‘.
So just checking the returned value is enough to write a safe test. Here is an example:
1 2 3 4 5 6 7 8 | $img_id = get_image_id_by_url( $some_url ); if ( $img_id ) { // do something ... set_post_thumbnail( $post_id, $img_id ); } else { // do otherthing ... echo 'The image could not be found in the database.'; } |
$img_id = get_image_id_by_url( $some_url ); if ( $img_id ) { // do something ... set_post_thumbnail( $post_id, $img_id ); } else { // do otherthing ... echo 'The image could not be found in the database.'; }
Discussion
Lets talk about that in the comments.
2 Responses to “Quickly get the image ID by its URL in WordPress”
Hi Martin, Thanks for this resource. I’m somewhat new to WordPress. How would you make this into a shortcake? Thanks!
Sorry, I do not (yet) know shortcake.