How do I set a featured image (thumbnail) by image URL when using wp_insert_post()?

  • While looking through the function reference entry for wp_insert_post(), I noticed that there's no parameter in the array it requires which will allow me to set the 'Featured Image' for a post, displayed as the post thumbnail in my theme.

    I have looked into functions like set_post_thumbnail(), as suggested by Mr. Bennett, but this seems to be a relatively new addition to WordPress itself and the WordPress codex. As such, there aren't any sources that I can find which explain how the $thumbnail_id parameter should be acquired and supplied. If this really is the function to use, in what way could I provide it with a valid $thumbnail_id parameter when all I have is an image URL?

    Thanks in advance!

  • Rob Vermeer

    Rob Vermeer Correct answer

    9 years ago

    You can set an image as post thumbnail when it is in your media library. To add an image in your media library you need to upload it to your server. WordPress already has a function for putting images in your media library, you only need a script that uploads your file.

    Usage:

    Generate_Featured_Image( '../wp-content/my_image.jpg', $post_id );
    
    // $post_id is Numeric ID... You can also get the ID with:
    wp_insert_post()
    

    Function:

    function Generate_Featured_Image( $image_url, $post_id  ){
        $upload_dir = wp_upload_dir();
        $image_data = file_get_contents($image_url);
        $filename = basename($image_url);
        if(wp_mkdir_p($upload_dir['path']))
          $file = $upload_dir['path'] . '/' . $filename;
        else
          $file = $upload_dir['basedir'] . '/' . $filename;
        file_put_contents($file, $image_data);
    
        $wp_filetype = wp_check_filetype($filename, null );
        $attachment = array(
            'post_mime_type' => $wp_filetype['type'],
            'post_title' => sanitize_file_name($filename),
            'post_content' => '',
            'post_status' => 'inherit'
        );
        $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $attach_data = wp_generate_attachment_metadata( $attach_id, $file );
        $res1= wp_update_attachment_metadata( $attach_id, $attach_data );
        $res2= set_post_thumbnail( $post_id, $attach_id );
    }
    

    http://codex.wordpress.org/Function_Reference/wp_upload_dir

    http://codex.wordpress.org/Function_Reference/wp_insert_attachment


    EDIT: Added path creation

    http://codex.wordpress.org/Function_Reference/wp_mkdir_p

    Thank you for your efforts! This only works when using $upload_dir'basedir' though, because when I inspect the attachment through the post edit interface it is referenced as .../uploads/FILENAME.EXT while $upload_dir['path'] would store it in something like .../uploads/2012/02/FILENAME.EXT. It might be even better to somehow change how the file is referenced, but I wouldn't know how.

    Added path creation in my answer.

    Appreciate your quick response :). I still get the same result however, here's a screenshot displaying my problem: http://i.imgur.com/iKTNs.png . The upper section is the result of placing an echo in your conditional, just to see what's going on.

    Changed it again, didn't pass the full path to wp_insert_attachment and wp_generate_attachment_metadata. Hope this will solve the problem.

    Works flawlessly, thank you so much! This has also fixed a sizing issue, which was apparently caused by incorrect paths (even though the image would show up). Couldn't be any better!

    Thanks for your great code. Only one amendment was needed to get it to work with my CSV import and that was prepending the postid to the filename to ensure the image files remain unique.

    Let me also heap on the praise. Love this snippet of code. Thanks for saving me hours!

    Just wondering: Is this safe? Is there a risk of someone disguising an image, or does wp_check_filetype() take care of that?

    I used the code above and slightly amended to get featured images which are named as the post slug (which is quite time consuming if you run thousands of posts): `code`

    usage of `file_get_contents` with a URL will not work if `allow_url_fopen` is disabled in `php.ini` - `wp_remote_get` will be more highly compatible across different WP environments

    Warning: This answer rewrites the file if it has the same name, beware. It should generate names using $post_id or at least uniqid()

    When I use this, the images created in "uploads" have a file size of zero.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM