Advertisement
Creative Coding

Sharing the WordPress Love With Non-Image Media Attachments

by

While WordPress easily displays images attached to your pages and posts (even without an attachment.php file), the other allowed media types (audio, video, document, text, archive, code, interactive) don't get the same love – save a direct link to the attachment file. But, you don't have to resort to uploading your audio, video, or other non-image media attachments elsewhere (like YouTube) in order to display them on your WordPress site. Using the default Twenty Eleven theme as an example, I'll show you WordPress' built-in functions for sharing the love with non-image media attachments.


How WordPress Handles Attachments by Default

Under the hood, media items are just WordPress posts, therefore, they are displayed according to the WordPress template hierarchy. The template loader does a check to see if the post is an attachment and has an attachment template. If an attachment template does not exist, WordPress will fall back to the single post template or the default index.php template (if the single post template does not exist).


Template Check

In the single post or index.php templates, WordPress themes will likely display the content using the_content. This function has a default filter attached to it – prepend_attachment – that will automatically add an attachment link to the page (using the wp_get_attachment_link function) if it determines that this is an attachment post. However, the arguments used here in the call to wp_get_attachment_link will only provide actual display for image attachments – non-image attachment files only get a direct link to the attachment file. (Where's the love?) We could potentially display more than just a link for non-image attachments with a simple change of arguments to wp_get_attachment_link, but unfortunately we don't have a way to change the arguments before the function is called.


Default Image Attachment Display vs. Default Non-Image Attachment Display

So let's take a look at what we can do to show our non-image attachments some love.


Taking Control of Non-Image Media Attachment Display

Step 1 Determine the File Type

The first thing we'll do is determine the file type of the attachment. WordPress allows uploading of several file types, found in the get_allowed_mime_types function shown below.


Default Allowed File Types

Although the Media Library admin screen only shows filters for the three default file types, the Edit page for each media item shows the exact file type. The file type is in the MIME format (MIME is a long-standing standard for classifying file types on the Internet) which has two parts: type and subtype separated by the /. In the image below, the type is "video" and the subtype is "mp4." This knowledge will come in handy for step 2.


Default File Types Shown in Media Library

File Types Shown on Edit Media Page

Built-In WordPress Function

WordPress has a built-in function for determining the file type of an attachment using the attachment post ID.

get_post_mime_type($ID)

This function will return the file type in MIME format, just as it's shown on the media item's edit page in the admin.
Now we're ready to take control of displaying non-image attachments in our theme template files.

Step 2 Create Theme Template File


Template Hierarchy

As shown in the image, the WordPress template hierarchy has four possible attachment templates it will look for after it determines that we are displaying an attachment post. We can either handle the display of each file type in the attachment.php file or we can create separate template files for each MIME type and/or MIME subtype. Let's take a look at these options.

Option 1. attachment.php File

We can handle the display of each file type in attachment.php using our handy get_post_mime_type function.

First, we'll get the file type of the attachment (while inside the loop):

<?php $type = get_post_mime_type( $post->ID ); ?>

Then, we can do a switch statement on the file type to provide the code to display each type:

<?php
	switch ( $type ) {
		case '{mimetype}/{mimesubtype}':
			// code to display file type
		break;
		default:
			// default code
?>

So if we'd like to display audio (mp3) and video (mp4) attachments, our switch statement would look like this:

<?php
	switch ( $type ) {
		case 'audio/mpeg':
			// code to display file type
		break;
		case 'video/mp4':
			// code to display file type
		break;
		default:
			// default code
?>

Using attachment.php is great if you only have a few file types to display (or your display for each file type will follow the same basic layout) as it allows us to keep our code in one file. If we have several file types and/or you plan to customize the display layout for each file type, you'll want to take a look at option 2.

Option 2. $mimetype.php, $mimesubtype.php, or $mimetype_$mimesubtype.php

attachment.php is actually the fallback template for template files with the name of the MIME type or MIME subtype of the current attachment post. WordPress will look for files with names like $mimetype.php, $mimesubtype.php, or $mimetype_$mimesubtype.php before falling back to attachment.php.

So instead of calling get_post_mime_type and using a switch statement, we can just create a template file with the name of the MIME type or subtype:

  • audio.php
  • mpeg.php
  • audio_mpeg.php

and place the code to display that file type.

Note: The file names are listed in the order in which WordPress will call them. So $mimetype.php first, then fallback to $mimesubtype.php, then fallback to $mimetype_$mimesubtype.php.

Now let's look at some examples.


Examples

Displaying Documents

I don't know about you, but I personally dislike having to download a document to my computer just to view it. Let's enlist the help of the embeddable Google Docs Viewer. It can display PDFs, spreadsheets, presentations and many other file types listed in Google Help. There's no requirement for your documents to be hosted on Google Docs as it will embed a viewer right in the page by passing it a file URL and setting the embedded parameter to true.

Here's how we would handle displaying documents using the Google Docs Viewer in attachment.php after getting the file type:

switch( $type ) {
	case 'application/pdf':
	case 'application/msword': ?>
			<iframe src="http://docs.google.com/viewer?url=<?php echo wp_get_attachment_url( $post->ID ) ?>&embedded=true" width="591" height="600" style="border: none;"></iframe>
	<?php break;
	default:
		// default code
	break;
}

Or, we could create one of the following template files:

  • application.php
  • pdf.php
  • application_pdf.php

and place the following code where you'd like to display the content inside the loop:

	<iframe src="http://docs.google.com/viewer?url=<?php echo wp_get_attachment_url( $post->ID ) ?>&embedded=true" width="591" height="600" style="border: none;"></iframe>

Notice that we are passing the URL of the attachment file to the Google Docs viewer using the wp_get_attachment_url function.

Final Result:

Audio

To display (play) audio files uploaded to WordPress and provide a consistent cross-browser experience, we're going to enlist the help of the lightweight audio.js library that allows us to use the HTML5 audio tag anywhere, falling back to flash in browsers that don't support HTML5 audio yet.

First, download and place the audio.js files in your theme. Then, in your functions.php file, add the code to enqueue the audio.js javascript on attachment pages only (following best practices). I'm sure there are other ways to do this – including using the recommended wp_enqueue_scripts action and some conditional statements – however, I'm going to illustrate the method in this article: Quick Tip: Including JavaScript and CSS Only On Certain Site Pages

add_filter( 'attachment_template', 'ncb_attachment_template' );

function ncb_attachment_template( $template_path ) {
	wp_enqueue_script( 'audio-js', get_template_directory_uri() . '/js/audiojs/audiojs/audio.min.js' );
	add_action( 'wp_head', 'ncb_audio_js' );
	
	return $template_path;
}

function ncb_audio_js() {
	echo '<script>audiojs.events.ready(function() {
		var as = audiojs.createAll();
	});
	</script>';
}

Then, we can add the following code to our attachment.php file:

<?php
case 'audio/mpeg': ?>
	<audio controls><source src="<?php echo wp_get_attachment_url( $post->ID ); ?>" type="audio/mpeg" /></audio>
	<?php break; ?>

Here's our full switch statement up to this point:

<?php
switch( $type ) {
	case 'application/pdf':
	case 'application/msword': ?>
		<iframe src="http://docs.google.com/viewer?url=<?php echo wp_get_attachment_url( $post->ID ) ?>&embedded=true" width="591" height="600" style="border: none;"></iframe>
	<?php break;
	case 'audio/mpeg': ?>
		<audio><source src="<?php echo wp_get_attachment_url( $post->ID ); ?>" type="audio/mpeg" /></audio>
	<?php break;
	default:
		// default code
	break;
}

Or, we could create one of the following template files:

  • audio.php
  • mpeg.php
  • audio_mpeg.php

and add our audio code inside the loop where we'd like to display the content:

	<audio><source src="<?php echo wp_get_attachment_url( $post->ID ); ?>" type="audio/mpeg" /></audio>

Note: If you use file type template files, the JavaScript needs to be enqueued on those pages only.

Final Result:

Video

We can display (play) video files uploaded to WordPress much the same as audio, except we're going to enlist the help of the video.js library that allows us to use the HTML5 video tag anywhere, falling back to flash in browsers that don't support HTML5 video yet.

Just as with audio, we'll download the files, add them to our theme directory, and enqueue the video.js javascript on attachment pages only, save for the addition of a CSS file:

wp_enqueue_script( 'video-js', get_template_directory_uri() . '/js/video-js/video.min.js' );
wp_enqueue_style( 'video-js-css', get_template_directory_uri() . '/js/video-js/video-js.min.css' );

Here's the full functions.php snippet:

add_filter( 'attachment_template', 'ncb_attachment_template' );

function ncb_attachment_template( $template_path ) {
	wp_enqueue_script( 'audio-js', get_template_directory_uri() . '/js/audiojs/audiojs/audio.min.js' );
	add_action( 'wp_head', 'ncb_audio_js' );

	wp_enqueue_script( 'video-js', get_template_directory_uri() . '/js/video-js/video.min.js' );
	wp_enqueue_style( 'video-js-css', get_template_directory_uri() . '/js/video-js/video-js.min.css' );

	
	return $template_path;
}

function ncb_audio_js() {
	echo '<script>audiojs.events.ready(function() {
		var as = audiojs.createAll();
	});
	</script>';
}

Then, we can add the following code to our attachment.php file:

<?php
	case 'video/mp4': ?>
		<video class="video-js vjs-default-skin" controls data-setup="{}"><source src="<?php echo wp_get_attachment_url( $post->ID ) ?>" type='video/mp4' /></video>';
	<?php break;

Here's our full switch statement:

<?php
switch( $type ) {
	case 'application/pdf':
	case 'application/msword': ?>
		<iframe src="http://docs.google.com/viewer?url=<?php echo wp_get_attachment_url( $post->ID ) ?>&embedded=true" width="591" height="600" style="border: none;"></iframe>
	<?php break;
	case 'audio/mpeg': ?>
		<audio controls><source src="<?php echo wp_get_attachment_url( $post->ID ); ?>" type="audio/mpeg" /></audio>
	<?php break;
	case 'video/mp4': ?>
		<video class="video-js vjs-default-skin" controls data-setup="{}"><source src="<?php echo wp_get_attachment_url( $post->ID ) ?>" type='video/mp4' /></video>';
<?php break;
	default:
		// default code
	break;
}

Or, we could create one of the following template files:

  • video.php
  • mp4.php
  • video_mp4.php

and add our video code inside the loop where we'd like to display the content:

	<video class="video-js vjs-default-skin" controls data-setup="{}"><source src="<?php echo wp_get_attachment_url( $post->ID ) ?>" type='video/mp4' /></video>

Remember: When using file type template files instead of attachment.php, you will need to change the name of the filter used to call the function that enqueues your JavaScript.

Final Result:


Summary

Non-image media attachments in WordPress need love, too! Using only two WordPress functions, you can keep your media files on your site and customize the display and layout of any of the allowed file types.

Download and/or fork the working code on Github.

References in This Article

WordPress functions

WordPress template files

  • attachment.php
  • index.php
  • single.php
  • $mimetype.php
  • $mimesubtype.php
  • $mimetype_$mimesubtype.php
Related Posts
  • Code
    Creative Coding
    Advanced Use of Attachments in WordPress: Creating Custom Queries for AttachmentsAdvanced use of attachments in wordpress 400
    This tutorial is the second in a four part series in which you'll learn some techniques for working with images in attachments in WordPress which give you advanced options.Read More…
  • Code
    Theme Development
    Custom Controls in the Theme CustomizerTheme customizer custom control 400
    In the last article, we explored the advanced controls available in the Theme Customizer, and how to implement them. We’re going to look at how to create our own custom control, allowing you to choose which Category of Posts are displayed on the home page. To get started, download version 0.6.0 of our Theme Customizer Example.Read More…
  • Code
    Theme Development
    Creating a WordPress Theme from Static HTML: Creating an Archive TemplateCreating wordpress theme from html 400
    If you've been working your way through this series, you now have a functioning theme with two page templates. The steps I've demonstrated to this point are: preparing your markup for WordPress converting your HTML to PHP and splitting your file into template files editing the stylesheet and uploading your theme to WordPress adding a loop to your index file adding meta tags, the wp_head hook and the site title and description to your header file adding a navigation menu adding widget areas to the header and sidebar adding widget areas, a colophon and the wp_footer hook to the footer file creating template files for static pages. Read More…
  • Code
    Theme Development
    Creating a WordPress Theme from Static HTML - Creating a Page TemplateCreating wordpress theme from html 400
    So far in this series, I've shown you how to create a fully functioning WordPress theme from static HTML. We've covered the following steps: preparing your markup for WordPress converting your HTML to PHP and splitting your file into template files editing the stylesheet and uploading your theme to WordPress adding a loop to your index file adding meta tags, the wp_head hook and the site title and description to your header file adding a navigation menu adding widget areas to the header and sidebar adding widget areas, a colophon and the wp_footer hook to the footer file. At the moment, your theme only has one template file for displaying content—the index.php file. A powerful feature of WordPress is the ability to use template files for different kinds of content.Read More…
  • Code
    Theme Development
    Creating a WordPress Theme From Static HTML: Adding a LoopCreating wordpress theme from html 400
    In the first three parts of this series, you learned how to prepare static HTML for WordPress and to create a theme by splitting your HTML file into a set of template files and editing the stylesheet. You then uploaded your theme to WordPress and activated it. The theme still isn't displaying any content you add via the WordPress admin however; to do that you need to add a loop to your template files.Read More…
  • Code
    Creative Coding
    How to Add Custom Fields to AttachmentsHow to add custom fields to attachments 400
    You should be familiar with custom fields in WordPress. We use them on a post or a page to add extra data. In WordPress attachments are also saved as posts, so custom fields are available for them too. Today we'll see how we can add some custom fields so that attachments can carry more information than just the default data.Read More…