Get the first image from post content (eg.: hotlinked images)

I am using this code directly from the codex.

function echo_first_image ($postID)
{                   
    $args = array(
    'numberposts' => 1,
    'order'=> 'ASC',
    'post_mime_type' => 'image',
    'post_parent' => $postID,
    'post_status' => null,
    'post_type' => 'attachment'
    );

    $attachments = get_children( $args );

    //print_r($attachments);

    if ($attachments) {
        foreach($attachments as $attachment) {
            $image_attributes = wp_get_attachment_image_src( $attachment->ID, 'thumbnail' )  ? wp_get_attachment_image_src( $attachment->ID, 'thumbnail' ) : wp_get_attachment_image_src( $attachment->ID, 'full' );

            echo '<img src="'.wp_get_attachment_thumb_url( $attachment->ID ).'" class="current">';

        }
    }
}

I call it within the loop like this echo_first_image ($post->ID);

Read More

The function does call but nothing gets output … as far as I can see there is nothing in $attachments

I do have an image in the post I am using. It’s not a featured image or in a gallery, just in the post.

Am I doing something wrong, or is there something wrong with the code in the first place?

Related posts

Leave a Reply

6 comments

  1. If you want display an image that is inserted into your content (a hotlinked image, for example), you must use a function like this (source):

    add in functions.php:

    function catch_that_image() {
      global $post, $posts;
      $first_img = '';
      ob_start();
      ob_end_clean();
      $output = preg_match_all('/<img.+src=['"]([^'"]+)['"].*>/i', $post->post_content, $matches);
      $first_img = $matches [1] [0];
    
      if(empty($first_img)){ //Defines a default image
        $first_img = "/images/default.jpg";
      }
      return $first_img;
    }
    

    Then place <?php echo catch_that_image() ?> where you want display the image.

    Note: a hotlinked image just placed in your content can’t be set as Featured Image, a bultin WordPress’feature.

  2. I suggest two ways:

    Using a Plugin

    I would consider using the Get The Image plugin, so you could do something like:

    $args = array(
        'post_id' => <id>
        'image_scan' => true
    );
    get_the_image($args);
    

    The above will try to do things in this order:

    1. Look for the post thumbnail
    2. Look for the first attached image
    3. Scan the post content for a inserted image.

    Building support in your theme

    However, I’m using a function in a plugin that implements the first two items of the list above.

    function gpi_find_image_id($post_id) {
        if (!$img_id = get_post_thumbnail_id ($post_id)) {
            $attachments = get_children(array(
                'post_parent' => $post_id,
                'post_type' => 'attachment',
                'numberposts' => 1,
                'post_mime_type' => 'image'
            ));
            if (is_array($attachments)) foreach ($attachments as $a)
                $img_id = $a->ID;
        }
        if ($img_id)
            return $img_id;
        return false;
    }
    

    You can adapt it to also match the third item within Diana’s snippet:

    function find_img_src($post) {
        if (!$img = gpi_find_image_id($post->ID))
            if ($img = preg_match_all('/<img.+src=['"]([^'"]+)['"].*>/i', $post->post_content, $matches))
                $img = $matches[1][0];
        if (is_int($img)) {
            $img = wp_get_attachment_image_src($img);
            $img = $img[0];
        }
        return $img;
    }
    

    Just stick these two functions in your functions.php file and use them in the loop like:

    <?php while (have_posts()) : the_post(); ?>
        <?php if ($img_src = find_img_src($post) : ?>
            <img src="<?php echo $img_src; ?>" />
        <?php endif; ?>
    <?php endwhile; ?>
    
  3. the code seems perfectly safe. like you said, you don’t have any image attached to the post.

    Consider going to the media admin panel and attach a image to that post.

    Alternately, scrap the post content with a regex for images in it.

  4. I understand this is very old question, but i am putting my answer here since most voted answer is not appropriate for people who new to PHP.

    preg_match is not a good approach for parsing HTML in PHP since preg_match is for regular expression and HTML is not regular expression.

    We can use DOM instead.

    function firstImg($html){
      $dom = new DOMDocument;
      $dom->loadHTML($html);
      $images = $dom->getElementsByTagName('img');
      foreach ($images as $image) {
        return $image->getAttribute('src');
      }
      return false;
    }
    

    Using DOM is really good since you can do more thing other than just getting first image and it is right way to parse html.

    I wish i can put answer for using wordpress functions (functions from CODEX and core) to get first image but that is also the problem that i am dealing with.

    This is not answer for every case!

    Consider the case of image size optimization. In that case, you can’t just use this code because the post can contain any size of image.

  5. This code works for me:

    function get_first_image( $post_id ) {
        $attach = get_children( array(
            'post_parent'    => $post_id,
            'post_type'      => 'attachment',
            'post_mime_type' => 'image',
            'order'          => 'DESC',
            'numberposts'    => 1
        ) );
        if( is_array( $attach ) && is_object( current( $attach ) ) ) {
            return current( $attach )->guid;
        }
    }
    
  6. If you are trying to find an attachment post id with attachment_url_to_postid once you find an image in the content, you may not find that id if the image you found is a scaled version of the image.

    If you are not worried about similarly named images, you can replace “-800×600.jpg” with preg_replace:

    $first_img_url_unscaled = preg_replace(
       '/-d+xd+.(jpg|jpeg|gif|png|svg|tiff|webp|heif|heic)$/i',
       '.${1}',
       $first_img_url,
    );
    

    You can also search the database more manually for the attachment id if you are concerned about misleading file names (e.g. cats-800×600.jpg could be a resize of an old cat image and the current cats.jpg is actually a picture of a goose).