12

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);

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?

6 Answers 6

29

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.

6
  • Yes I've seen that code around ... seems like a bit of a hack, you'd think there'd be a "WordPress" way ... I wonder why I need to use preg_match when the codex says you can do it as I posted above. That's my question really to be honest. Is the code that I posted wrong? ... more-so than trying to get it working really. But thanks I may end up having to use this. I don't understand the significance of "an image just placed in your content can't be set as Featured Image". Does that impact upon this in some way. I am just trying to display the first image from the post, not the featured image. Jul 31, 2012 at 19:06
  • There's a big difference between place an image link inside your post/page content and attach an image. You can attach an image without displaying it at all. Codex example is about getting a file attached to your post/page, there's no way to get a image placed inside by linking, also hotlinking is not a feature WP will deal with without PHP regex.
    – Diana
    Jul 31, 2012 at 22:52
  • About the COdex reference: as you can see the doc is called after the function name get_childre, an attachment is a children post so this example only can work for attached content.
    – Diana
    Jul 31, 2012 at 23:01
  • Yes I know I can attach an image without inserting it, that bit is clear ... but I don't see how you can insert an image without attaching it ... when I press upload/insert, upload a file from my computer and press insert into post and update then go to media library library it tells me that the image I uploaded is "attached" to the post ? ... or are we talking semantics here because I understand what you're saying about that bit of code only working for attached images. Aug 1, 2012 at 0:01
  • 1
    You can hotlink an image file anywhere. When clicking Insert Image/Media, there's a tab "From URL", where you inform an image URL, i.e. imageshack service. The regex will be able to get this image ("as is"), but WP will not be able to use this image as Featured Image, for instance.
    – Diana
    Aug 1, 2012 at 2:37
3

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);
        if ($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; ?>
2
  • Theme is to be for sale commercially so I don't want to tell the end user they have to install a plugin, but thanks. Jul 31, 2012 at 19:11
  • @byronyasgur Edited the answer to clarify that I gave you two solutions. You don't need to install a plugin to follow the second one. Jul 31, 2012 at 21:41
2

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.

2
  • Do I have a misunderstanding of what "attached" means exactly? .... I DO have an image in the post ... is it not attached when you click 'add to post'? Jul 31, 2012 at 19:04
  • 1
    from your question, it seemed that you typed the html code linking to a image not necessarily attached by wp.
    – pcarvalho
    Aug 1, 2012 at 2:57
2

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.

1
  • "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." is not true -- anything with text can be parsed as Regular Expressions
    – bresson
    Jan 3, 2021 at 17:15
1

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;
    }
}
0

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 "-800x600.jpg" with preg_replace:

$first_img_url_unscaled = preg_replace(
   '/-\d+x\d+\.(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-800x600.jpg could be a resize of an old cat image and the current cats.jpg is actually a picture of a goose).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.