How to Upload a File With WordPress’ Secret Native Functions
Like any good CMS, WordPress offers a bunch of functions, some of which may be hidden under the hood. For example, did you know that WordPress provides dedicated functions for uploading files, figuring out the file type and adding attachments?
In this Weekend WordPress Project I’ll show you how you can use these native functions to upload media, in case you need to do it outside the regular media upload box.
Let’s create a page template in the Twenty Fifteen theme, which will let users upload a single image and some text via a form. The idea is that we’ll let them create draft posts, which we’ll go through so we can publish ones we like.
Step 1. Creating a Child Theme
If you need a detailed description of how to do this we have a child themes guide. But here’s the nuts and bolts version:
In your themes directory create a folder named “twentyfifteen-upload-test.” Within that folder create a
style.css. Open it up and add the following content:
Then, create a
functions.php file which will load the parent theme’s styles. The code to place within this file is the following:
At this stage you should see the theme pop up in the Appearance section and you can activate it. If you’ve done everything correctly, you should see no changes in the frontend.
Step 2. Submission Page Template
Next, let’s create the page template that will display our submission form. The form will contain three fields: title, description and image. We won’t worry about protecting our form with a captcha, but we will create a nonce, which serves as some protection (you can learn more about nonces here).
To create a page template all we need to do is create a new file. Let’s name it
template-submit.php and start with a template declaration:
Once saved, you should be able to create a page and assign it the Submission Page template, like I have done in the screenshot below:
Time to add some content to the template! I actually cheated and essentially copy-pasted the code for the
page.php file from the parent theme. In the process I removed the code which determines if comments are needed – since they aren’t – and I modified the
get_template_part() function to retrieve the
content-submit-page.php file which you should create now. The following code should be placed in the
Place the code below into the
content-submit-page.php file. Again, I have copied all of this from the
content-page.php from the parent theme, we’re recycling most of the code.
You should be able to view the page and see the exact same result but instead of being displayed using the
content-page.php file from the child theme, the content now comes from the
content-submit-page.php file in our child theme.
Creating the Form
The form doesn’t contain anything special, it’s your run-of-the-mill HTML form. Our three fields will be added, plus a nonce field which will be used to verify the submission and minimize the chance of automated submits.
The form should be placed within the
.entry-content div at the very end. The code I have used is the following:
Note that the action is set to
<?php echo admin_url( 'admin-ajax.php' ) ?>. I like to route form submissions to the
admin-ajax.php file because it allows me to manage all the submitted data from within the functions file using hooks, more on this soon.
A nonce has also been added which we’ll check when we’re processing the form. The idea is that this helps us check permission and intent. If the nonce doesn’t check out we can stop the function in its tracks to avoid spam.
Note the accept parameter for the file input. This is an attribute introduced in HTML 5, it allows you to narrow down accepted file types. I’ve chosen to accept any image type.
Processing The Form
Since I routed the form submission to the
admin-ajax.php file there is one important piece of information we’ll need to process the data – the value of the
action field. I have set this to
submit_content. This is used to create the required hook, place the following in the functions file:
If you would like some in-depth information about how and why this works, take a look at our guide on AJAX. For now, let’s continue by writing the contents of the
The function should accomplish the following:
- Add a draft post to the database with the given title and content
- Upload the selected image
- Attach the image to the created post
Let’s start with the first step, just inserting the post without the image. This is easy enough, all we need to do is create an array of post data and use the
wp_insert_post() function to add it.
We use the post title and content given by the user and set the post status to draft. Other information will be filled out automatically. The author will be set to the default admin user.
$post_id variable will contain the new post’s ID if the insertion is successful. Then, we redirect the user to a thank you page which you can set up to be a regular page.
Since these function are usually used for AJAX it is important to add the
die()> function at the end, otherwise the page may echo a 0 character.
So far so good, the only thing missing is the image, let’s go ahead and add that in as well.
Uploading an Image
In this step we will upload the image, assign it to the post we just created and make it the featured image of said post as well. This requires a series of sub-steps which are handled by WordPress functions.
- The image must be transferred to the server, to a temporary location
- The file type and final upload directory must be determined
- An attachment must be created for the image and attached to a post (if applicable)
- The attachment metadata must be added to the attachment
- Make the image the featured image for the post
Let’s look at the full code first, then I’ll explain the little bits and pieces. The code below is the final and full code of the
Once the post has been added, the first thing we do is upload the image to a temporary location. This is handled by the
wp_upload_bits() function. The first parameter is the image name, the second is deprecated, the third is the content of the file which can be read using the
wp_check_filetype() function we figure out the file type. This will be used when adding the file as an attachment.
Next we find the upload directory using the
wp_upload_dir() function. We’ll use the information when adding the attachment.
Finally, we create a data array for our attachment. It contains a guid which will be the path to the file. The file is actually moved here by the
wp_insert_attachment() function. The post’s mime type is read from the file type information we retrieved, the post title is pulled from the file information. The post content is set to an empty string while the post status should be “inherit”.
We are now ready to insert the attachment using the
wp_insert_attachment() function. The first parameter contains the attachment data, the second contains the file. The third parameter is a post id. if you want to attach the image to a post you should indicate it here, otherwise set it to 0. In our case we want to attach it to
$post_id – the post we just created.
We need to generate some metadata for the attachment in order for it to work properly. First you need to use the
wp_generate_attachment_metadata() function, passing it the attachment’s ID and the uploaded file. You then need to use
wp_update_attachment_metadata() to add the metadata to the database, passing it the attachment ID and the newly generated metadata.
Finally we update the
_thumbnail_id post meta which stores which image is set as the featured image for a post.
All done, at this stage you have a working form. Submitting a title, description and an image should result in a draft post in the backend with the given title, description and the image set as the featured image.
Clarifying Images and Attachments
Don’t worry if you are a bit confused about the last step, there was a lot of terminology in there which is not encountered every day. The three main things in there are image, attachment and
An image is simply a file which contains an image of some sorts. You could upload a million images to your uploads folder but they would never show up in WordPress. WordPress doesn’t list the contents of an image directory when showing images, it looks in the database.
This is where attachments come in. They are not very well named (for historic reasons) because they do not have to be attached to anything. An attachment is simply a special post type which points to a media item. This item can be anything from an image to a video.
An attachment contains information about the attachment, like it’s name, when it was created and so on. In the metadata of the attachment a field also tells WordPress which media file belongs to the attachment. This is when it actually shows up in the Media section – when you have an attachment that also has a media file associated with it.
The reason they are called attachments is that you can attach them to posts but this is not longer necessary, you can have attachments that aren’t attached to any particular post. A good example of this is if you go to the Media section and just upload an image there.
A featured image is a property of a post. It tells the post which attachment is considered to be its featured image. A featured image is essentially an ID in the database that points the an attachment, which in turn points to an image file somewhere.
Creating a Simple Function
That being said, you can create a single function to do it for you by abstracting most of the code out. Here’s an example of a function you can use to easily upload an image by passing it member of the
$_FILES array you need, the post to attach it to (optional) and wether or not you want to make it the featured image (optional).
You can get get away with specifying the image only, this will simply upload it. If you specify a post ID you can attach it to a post and if you set the third parameter to true, the image will be set as the featured image for the post.
Here is how our
my_submission_processor() function would look if we used this function:
In the end, uploading an image with functions is a bit more complex than you might think because of the number of steps involved. You need to upload the image, create the attachment and generate the proper attachment meta data.
That said, the process is very modular, and as you sawit can be extracted out into a function very easily.
This method should be very useful for situations where you want to accept an image from the front-end without having to go through the image uploader or any other third party scripts.Tags: