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
 *
 * @param string $url  The URL to resolve.
 *
 * @return int The found post ID.
 * @global wpdb  $wpdb WordPress database abstraction object.
 *
 */
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;
}

6 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.