Get Attachment ID by image URL

This week I was doing some a development review for a Agency here in Rio and we saw that we needed to discover the Attachment ID based on the URL.

On version 4.0 WordPress introduced a function to allow you to grab the Attachment ID by image URL.

/**
 * Try to convert an attachment URL into a post ID.
 *
 * @since 4.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $url The URL to resolve.
 * @return int The found post ID.
 */
function attachment_url_to_postid( $url ) {
    global $wpdb;

    $dir = wp_upload_dir();
    $path = $url;

    if ( 0 === strpos( $path, $dir['baseurl'] . '/' ) ) {
        $path = substr( $path, strlen( $dir['baseurl'] . '/' ) );
    }

    $sql = $wpdb->prepare(
        "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = %s",
        $path
    );
    $post_id = $wpdb->get_var( $sql );
    if ( ! empty( $post_id ) ) {
        return (int) $post_id;
    }
}

Unfortunately this version of the code doesn't resolve the ID when we are dealing with URL's with the crop size of the image. Which in our case was a problem since we didn't had much control around the input.

Looking to resolve this issue I've built an wrapper around the attachment_url_to_postid function, that will remove the crop size if it exists:

function get_attachment_id_by_url( $url ) {
    $post_id = attachment_url_to_postid( $url );

    if ( ! $post_id ){
        $dir = wp_upload_dir();
        $path = $url;
        if ( 0 === strpos( $path, $dir['baseurl'] . '/' ) ) {
            $path = substr( $path, strlen( $dir['baseurl'] . '/' ) );
        }

        if ( preg_match( '/^(.*)(\-\d*x\d*)(\.\w{1,})/i', $path, $matches ) ){
            $url = $dir['baseurl'] . '/' . $matches[1] . $matches[3];
            $post_id = attachment_url_to_postid( $url );
        }
    }

    return (int) $post_id;
}

Discussions — 6 Responses

  • devbas September 19, 2015 on 5:44 am

    Thanks for the clear explanation! But I think $id in the get_attachment_id_by_url() function needs to be $post_id?

    Reply
    • Gustavo Bordoni devbas September 19, 2015 on 11:00 am

      Thanks a lot for pointing it out man. Now it's fixed.

      Reply
  • Wilcho April 13, 2016 on 5:56 pm

    Great tip, thanks

    Reply
  • Chris May 11, 2016 on 10:01 am

    Method: attachment_url_to_postid works in WordPress 4.5.2 in you? Beacuse I have problem with that.

    Reply
    • Gustavo Bordoni Chris May 16, 2016 on 12:04 pm

      Hi Chris,

      Can you attach-me what problem you are currently having?

      My Best Regards,

      Reply
  • Ante Šepić October 28, 2016 on 1:29 pm

    Works flawlessly, thanks for sharing, you saved me time today :)

    Reply

Leave a Reply