Dissecting WordPress Themes Part 4: Attachment Hierarchy

In the last article, Dissecting WordPress Themes Part 3: Single-Post Hierarchy, we began our exploration of the WordPress Template Hierarchy with a review of the single-post hierarchy. In this article we’ll take a look at the template hierarchy for attachment pages. As you will recall from the prior article, the attachment page hierarchy falls back to single.php as does single-post.php and single-[post type].php. Also, single.php has index.php as its fallback template file. The attachment page hierarchy has several additional levels that we’ll explore in detail.

Before we get started there is a little bit of terminology that I should clarify. When you upload a file to the WordPress Media Library, it is stored in the filesystem of your WordPress installation in the wp-content/uploads directory. Once you insert that file into a post or page, it becomes an attachment. When the post or page is viewed, a reader may click on the attachment. The target of the attachment link may be the file itself or an attachment page depending on the option chosen when the attachment was inserted. The attachment page is an HTML page (generated by a PHP file, of course) that typically has information about the attachment. The format of the attachment page is entirely determined by the theme. You can also view the attachment page directly from the Media Library.

Upload Files to the Media Library

To demonstrate the attachment page hierarchy, we’ll first need to upload a few files to the Media Library. In order to demonstrate a variety of file types, lets upload a text file, an Excel file, a Word file, a JPEG file, and an Acrobat file.

I will use Notepad to create a text file called test.txt as shown below.

Text File

Text file created with Notepad.

I’ll use Microsoft Excel to create a spreadsheet called test.xls as shown below.

Spreadsheet

Spreadsheet created with Microsoft Excel.

I’ll use Microsoft Paint to create a JPEG file called test.jpg as shown below.

JPEG Image

JPEG image created with Microsoft Paint.

Finally, I’ll use Microsoft Word to create a Word file called test.doc and also save it as an Adobe Acrobat file called test.pdf as shown below.

Word Document

Document created with Microsoft Word.

Acrobat file

Acrobat file created with Microsoft Word.

Next, we’ll upload all of those files to the Media Library. Log in to the WordPress Administration Screen and select Media→Add New from the menu on the left side of the screen. Click the Select Files button.

Upload New Media page

You can upload files from the Upload New Media page.

Browse to where you saved your files and select all five of them. You will be returned to the Upload New Media page. Navigate to the Media Library page to view the page below.

Media Library with uplooaded files

The Media Library shows the uploaded files.

Exercise the Template Hierarchy

Where we left off in Part 3 we have a single.php file that includes content-[post format].php using the get_template_part() function call. We also have single-post.php to display the standard post type of post and single-my_book.php to display a custom post type that we created called my_book.

Let’s begin our study of the attachment page hierarchy by viewing an attachment page. Navigate to the Media Library, hover your mouse over the Excel spreadsheet file test.xls, and click View from the pop-up links. You should see the attachment page for this file using our single.php template, which includes content.php. The URL for this page includes the attachment_id in the query string (the actual ID value will likely be different for you).

Single.php

The template file single.php is used to view an attachment page. The URL uses a query string with the attachment ID to request the page.

Recall from the last article that attachment is one of the built-in post types, in addition to post, page, revision, and navigation menu. In that article we found that we could use post-[post type].php to override single.php. So, we should be able to use that pattern with single-attachment.php as well. Let’s copy our single.php file to single-attachment.php and change the trace message to In single-attachment.php. For our attachment page examples, the dynamic include based on post format is not useful, so we’ll put the Loop back into single-attachment.php and add a few more fields to the table. The complete single-attachment.php is shown below.

<?php
get_header(); 
echo "<p>In single-attachment.php</p>\n";

if (have_posts()) {   // if there are posts
	echo "<table>\n";
	echo "<tr><th>Attribute</th><th>Value</th></tr>\n";
	while (have_posts()) {   // start the loop
		the_post();
		echo "<tr><td>ID</td>";
		echo "<td>", get_the_ID(), "</td></tr>\n";
		echo "<tr><td>Title</td>";
		echo "<td>", get_the_title(), "</td></tr>\n";
		echo "<tr><td>Content</td>";
		echo "<td>", get_the_content(), "</td></tr>\n";
		echo "<tr><td>MIME type</td>";
		echo "<td>", get_post_mime_type(), "</td></tr>\n";
		echo "<tr><td>URL</td></td>";
		echo "<td><a href='", wp_get_attachment_url();
		echo "'>attachment</a></td></tr>";

		}
	echo "</table>\n";
} else {
	echo "<p>no posts to display</p>\n";
}

get_sidebar();
get_footer();
?>

If you now view the attachment page for test.xls again, you will see that single-attachment.php does override single.php. Also notice that the standard Loop code now retrieves the selected attachment page. We added the MIME type of the attachment by calling get_post_mime_type() and the URL of the attachment with a call to wp_get_attachment_url(). Note that the Content cell is blank. For attachment pages, the get_the_content() call returns the value of the attachment’s Description field, which you can populate from the Edit Media page.

Single-attachment.php

The template file single-attachment.php is used in place of single.php.

If you now click on the attachment link in the table, the browser will navigate to the attachment itself. Since this is an Excel spreadsheet, the browser should prompt you to either open the file or save it to your local machine (this functionality is browser-dependent). Access the attachment pages for the other files that you uploaded. Note the MIME type of each file as we’ll be using some of them shortly. I’ve listed them in the table below for reference.

Filename MIME Type
test.doc application/msword
test.xls application/vnd.ms-excel
test.txt text/plain
test.pdf application/pdf
test.jpg image/jpeg

The next level in the attachment page template hierarchy is attachment.php. Copy single-attachment.php to attachment.php and change the trace message to In attachment.php as shown in the code below.

<?php
get_header(); 
echo "<p>In attachment.php</p>\n";

if (have_posts()) {   // if there are posts
	echo "<table>\n";
	echo "<tr><th>Attribute</th><th>Value</th></tr>\n";
	while (have_posts()) {   // start the loop
		the_post();
		echo "<tr><td>ID</td>";
		echo "<td>", get_the_ID(), "</td></tr>\n";
		echo "<tr><td>Title</td>";
		echo "<td>", get_the_title(), "</td></tr>\n";
		echo "<tr><td>Content</td>";
		echo "<td>", get_the_content(), "</td></tr>\n";
		echo "<tr><td>MIME type</td>";
		echo "<td>", get_post_mime_type(), "</td></tr>\n";
		echo "<tr><td>URL</td></td>";
		echo "<td><a href='", wp_get_attachment_url();
		echo "'>attachment</a></td></tr>";

		}
	echo "</table>\n";
} else {
	echo "<p>no posts to display</p>\n";
}

get_sidebar();
get_footer();
?>

Choose one of the attachment pages, say test.txt, and note from the trace message that you are now running attachment.php instead of single-attachment.php. Click the attachment link and note that the browser is able to display the text/plain attachment directly and doesn’t need help from an external application.

attachment.php

The template file attachment.php replaces single-attachment.php in the hierarchy.

Next up in the hierarchy is a set of template files for individual MIME types. You would use these templates if you need to alter the structure of the generated page based on the particular MIME type of the attachment.  The first template in this series is [mimetype]_[subtype].php. This would result in a template file with a name like image_jpeg.php for the image/jpeg MIME type. Unfortunately, there is a bug in release 3.5.1 of WordPress which removes the underscore from the template filename. Because of this, I’ll instead create a template file called imagejpeg.php in order to demonstrate the functionality. Copy attachment.php to imagejpeg.php and change the trace message as shown.

<?php
get_header(); 
echo "<p>In imagejpeg.php</p>\n";

if (have_posts()) {   // if there are posts
	echo "<table>\n";
	echo "<tr><th>Attribute</th><th>Value</th></tr>\n";
	while (have_posts()) {   // start the loop
		the_post();
		echo "<tr><td>ID</td>";
		echo "<td>", get_the_ID(), "</td></tr>\n";
		echo "<tr><td>Title</td>";
		echo "<td>", get_the_title(), "</td></tr>\n";
		echo "<tr><td>Content</td>";
		echo "<td>", get_the_content(), "</td></tr>\n";
		echo "<tr><td>MIME type</td>";
		echo "<td>", get_post_mime_type(), "</td></tr>\n";
		echo "<tr><td>URL</td></td>";
		echo "<td><a href='", wp_get_attachment_url();
		echo "'>attachment</a></td></tr>";

		}
	echo "</table>\n";
} else {
	echo "<p>no posts to display</p>\n";
}

get_sidebar();
get_footer();
?>

Select the attachment page for the JPEG file test.jpg and note that we are now executing the new template file, imagejpeg.php. View attachment pages for the other files and notice that they still use attachment.php.

imagejpeg.php

The template file imagejpeg.php overrides attachment.php in the template hierarchy. A bug in the current version of WordPress removes the underscore that should be between the type and subtype.

Let’s create one more for illustration. Copy attachment.php to applicationpdf.php, change the trace message, and select the attachment page for the Acrobat file test.pdf. Notice that the new template file is being used. Click the attachment link. In most browsers the Acrobat file should display directly in the browser and not require application support.

The next template file in this hierarchy specifies only the subtype (the part of the MIME type after the “/”). For the MIME type image/jpeg, this would result in the template filename jpeg.php. Copy imagejpeg.php to jpeg.php and change the trace message. Select the application page for the image and note that now jpeg.php is executed instead of imagejpeg.php.

jpeg.php

The template file jpeg.php replaces imagejpeg.php in the template hierarchy.

And finally, one more level in the hierarchy for the primary MIME type (the part before the “/”). In the case of image/jpeg, this results in a template file called image.php. Copy jpeg.php to image.php, change the trace message, and select the image file again. Note that image.php is used to display the page.

image.php

The template file image.php overrides jpeg.php in the template file hierarchy.

Well, that’s probably a lot more hierarchy than you will ever need. It’s unlikely that you will ever need to use all of the MIME type levels, but they’re available if you do.

Link Media to a Post

In order to demonstrate the template hierarchy, we viewed the attachment pages for our files using the Media Library page. However, you would typically link to the attachment page from a post or page. Let’s demonstrate that now. Navigate to Posts→All Posts and select the Edit link under the Post 6 title. In the content editor, click after the sentence This is Post 6, and press Enter. Click the Add Media button and then the Media Library link. On the Insert Media dialog, select the JPEG image. In the Link To drop-down box on the right side of the page select Attachment Page. Click Insert into Post as shown below.

Insert Media page

The Insert Media page is used to insert (attach) a media file to a post or page. The Link To option allows you to select an attachment page instead of linking directly to the file.

Back on the Edit Post page, click Update.

Edit Post page

Once inserted, you can click on the image to go to the attachment page.

Click Visit Site and then select Post 6 from the index.php post list. You should now see the image in the Content cell of the table. Click the image to display the attachment page using the image.php template file as before.

In this article we continued our demonstration of the WordPress template hierarchy with a look at the hierarchy for attachment pages. The attachment page hierarchy shares the single.php file with the single-post hierarchy that we reviewed in the last article. The diagram below shows the area of the hierarchy that we’ve covered so far. In the next article, we’ll begin our exploration of the archive hierarchy with categories.

Template Hierarchy

The attachment page hierarchy includes single-attachment.php, attachment.php, and a set of media type template files.

References

Speak Your Mind

*