Get attachment ID by file path in WordPress

I know the path of the file and I like to get the attachment ID.

There’s a function wp_get_attachment_url() which requires the ID to get the URL but I need it reverse (with path not URL though)

Related posts

Leave a Reply

7 comments

  1. UPDATE: since wp 4.0.0 there’s a new function that could do the job. I didn’t tested it yet, but it’s this:

    https://developer.wordpress.org/reference/functions/attachment_url_to_postid/


    OLD ANSWER: so far, the best solution I’ve found out there, is the following:

    https://frankiejarrett.com/2013/05/get-an-attachment-id-by-url-in-wordpress/

    I think It’s the best for 2 reasons:

    • It does some integrity checks
    • [important!] it’s domain-agnostic. This makes for safe site moving. To me, this is a key feature.
  2. I used this cool snipped by pippinsplugins.com

    Add this function in your functions.php file

    // retrieves the attachment ID from the file URL
    function pippin_get_image_id($image_url) {
        global $wpdb;
        $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid='%s';", $image_url )); 
            return $attachment[0]; 
    }
    

    Then use this code in your page or template to store / print / use the ID:

    // set the image url
    $image_url = 'http://yoursite.com/wp-content/uploads/2011/02/14/image_name.jpg';
    
    // store the image ID in a var
    $image_id = pippin_get_image_id($image_url);
    
    // print the id
    echo $image_id;
    

    Original post here: https://pippinsplugins.com/retrieve-attachment-id-from-image-url/

    Hope ti helps 😉
    Francesco

  3. None of the other answers here appear to work properly or reliably for a file path. The answer using Pippin’s function also is flawed, and doesn’t really do things “the WordPress Way”.

    This function will support either a path OR a url, and relies on the built-in WordPress function attachment_url_to_postid to do the final processing properly:

    /**
     * Find the post ID for a file PATH or URL
     *
     * @param string $path
     *
     * @return int
     */
    function find_post_id_from_path( $path ) {
        // detect if is a media resize, and strip resize portion of file name
        if ( preg_match( '/(-d{1,4}xd{1,4}).(jpg|jpeg|png|gif)$/i', $path, $matches ) ) {
            $path = str_ireplace( $matches[1], '', $path );
        }
    
        // process and include the year / month folders so WP function below finds properly
        if ( preg_match( '/uploads/(d{1,4}/)?(d{1,2}/)?(.+)$/i', $path, $matches ) ) {
            unset( $matches[0] );
            $path = implode( '', $matches );
        }
    
        // at this point, $path contains the year/month/file name (without resize info)
    
        // call WP native function to find post ID properly
        return attachment_url_to_postid( $path );
    }
    
  4. Cropped URLs

    None of the previous answers supported ID lookup on attachment URLs that contain a crop.

    e.g: /uploads/2018/02/my-image-300x250.jpg v.s. /uploads/2018/02/my-image.jpg

    Solution

    Micah at WP Scholar wrote a blog post and uploaded the code to this Gist. It handles both original and cropped URL lookup.

    I included the code below as a reference but, if you find useful, I’d encourage you to leave a comment on his post or star the gist.

    /**
     * Get an attachment ID given a URL.
     * 
     * @param string $url
     *
     * @return int Attachment ID on success, 0 on failure
     */
    function get_attachment_id( $url ) {
    
        $attachment_id = 0;
    
        $dir = wp_upload_dir();
    
        if ( false !== strpos( $url, $dir['baseurl'] . '/' ) ) { // Is URL in uploads directory?
    
            $file = basename( $url );
    
            $query_args = array(
                'post_type'   => 'attachment',
                'post_status' => 'inherit',
                'fields'      => 'ids',
                'meta_query'  => array(
                    array(
                        'value'   => $file,
                        'compare' => 'LIKE',
                        'key'     => '_wp_attachment_metadata',
                    ),
                )
            );
    
            $query = new WP_Query( $query_args );
    
            if ( $query->have_posts() ) {
    
                foreach ( $query->posts as $post_id ) {
    
                    $meta = wp_get_attachment_metadata( $post_id );
    
                    $original_file       = basename( $meta['file'] );
                    $cropped_image_files = wp_list_pluck( $meta['sizes'], 'file' );
    
                    if ( $original_file === $file || in_array( $file, $cropped_image_files ) ) {
                        $attachment_id = $post_id;
                        break;
                    }
    
                }
    
            }
    
        }
    
        return $attachment_id;
    }
    

    Another pro with this solution is that we leverage the WP_Query class instead of making a direct SQL query to DB.

  5. Find IDs for resized images, PDFs and more

    Like GFargo pointed out, most of the answers assume the attachment is an image. Also attachment_url_to_postid assumes a url (not a file path).

    I believe this better answers the actual question when supplied a file (with path):

    function getAttachmentIDFromFile($filepath)
    {
        $file = basename($filepath);
        $query_args = array(
            'post_status' => 'any',
            'post_type'   => 'attachment',
            'fields'      => 'ids',
            'meta_query'  => array(
                array(
                    'value'   => $file,
                    'compare' => 'LIKE',
                ),
            )
        );
    
        $query = new WP_Query($query_args);
    
        if ($query->have_posts()) {
            return $query->posts[0]; //assume the first is correct; or process further if you need
        }
        return 0;
    }
    
  6. Based on the answer from @FrancescoCarlucci I could do some improvements.

    Sometimes, for example when you edit an image in WordPress, it creates a copy from the original and adds the copys upload path as post meta (key _wp_attached_file) which is not respected by the answer.

    Here the refined query that includes these edits:

    function jfw_get_image_id($file_url) {
        $file_path = ltrim(str_replace(wp_upload_dir()['baseurl'], '', $file_url), '/');
    
        global $wpdb;
        $statement = $wpdb->prepare("SELECT `ID` FROM `wp_posts` AS posts JOIN `wp_postmeta` AS meta on meta.`post_id`=posts.`ID` WHERE posts.`guid`='%s' OR (meta.`meta_key`='_wp_attached_file' AND meta.`meta_value` LIKE '%%%s');",
            $file_url,
            $file_path);
    
        $attachment = $wpdb->get_col($statement);
    
        if (count($attachment) < 1) {
            return false;
        }
    
        return $attachment[0]; 
    }