wordpress-generic

So you’ve got a WordPress theme that you’re either creating for the first time, or that you’d like to edit to suit your needs. You want to modify your theme’s functionality or add features— where to start?

This is a beginner’s introduction to the functions.php file in WordPress themes. You do not need experience in PHP to follow along, though you should have solid knowledge of HTML/CSS and be familiar with using WordPress.

What is functions.php?

The WordPress functions.php file is located in your theme’s directory (/wp-content/themes/your-theme/functions.php). The functions file is essentially a within-theme plugin. It is run during WordPress initialization on both the front and back ends, therefore enabling you to add features and customization specific to your theme.

WordPress contains numerous functions that you can take advantage of or alter / filter in your theme. You may, of course, also create your own functions in the functions.php file.

If you are relatively new to PHP and WordPress, it’s best to start with function snippets that have been written by other WordPress developers before you attempt to write your own custom functions. There are many commonly-used functions that should cover nearly all of your basic needs for theme customization. When you’ve thoroughly familiarized yourself with WordPress and learned some PHP, then you can tackle writing your own functions and plugins for more advanced customization.

Plugin or functions.php?

The key difference between putting your code in the functions.php file as opposed to writing a plugin is that plugins are independent from themes. If you are writing in features that are closely tied to other theme files (such as specially-styled post formats, for example), you should use functions.php. This way, the feature, its styles, and its code come packaged with your theme.

The advantage to plugins, alternately, is that they can be activated and deactivated on the fly, and will be persistent when the user changes themes. They can have their own outputted code and styles, all contained within the plugin files, which will be applied, regardless of theme.

It is a judgment call on what route is more appropriate for your needs. However, it is generally accepted that post thumbnails, post formats, custom comment callbacks, and similar theme-related features should be in the functions.php file.

Writing functions.php from scratch

If you are writing a functions file from scratch, create a new .php file in your theme’s directory and call it functions.php.

PHP 101: PHP scripts need to be contained within PHP delimiters, because although the server knows to look for PHP script in a .php file, these files can also contain non-PHP elements. Anything outside PHP delimiters will be interpreted as plain text or HTML.

All functions should go between the delimiters, like so:

<?php
	// all functions will go here
?>

Note: When you are searching online for functions, some sites and blogs will include the delimiters. Others will leave them off, assuming that you know to include them at the beginning and end of the file.

“Must-have” Features

Here are a few features (as of WordPress 3.3, aka “Sonny”) that every theme should seriously consider supporting.

Note: You will want to check if the function exists first for newer features, in case the installation of WordPress is older and doesn’t support the feature yet. This is done by enclosing the function in if (function_exists()) { … } (see examples below).

Menus

“Menus” are dynamic areas that users can populate with pages, posts, archives, etc. of their choosing via settings (Appearance / Menus on the back end). They are created using the register_nav_menus() function.

PHP 101: You can have more than one menu area if you wish, so the function supports an array. Arrays are PHP datatypes that can store multiple pieces of information.

WP workings: If you only want one menu, you can still set up the function the same way. Use an array, but only include one menu in it. Alternately: there is a function in WordPress that generates a single menu (register_nav_menu()), with a shortened format. However, behind the scenes it is actually still using the register_nav_menus() array with only one value. Therefore, it is up to you which option you choose: the outcome is still the same.

You will need to name your menus appropriately, because these names will show up on the back end as customizable areas.

PHP 101: The __( $string ) format is an international translation aid. If you were to leave it off and put something like ‘primary’ => ‘Primary Navigation’ instead, the text would print exactly as it is, even if the WordPress installation’s language was changed.

To display menus on the front end, you would place the following in your theme file:

<?php wp_nav_menu( array('menu' => 'Primary Navigation' )); ?>

By default, this outputs a container div with a class of “menu-{menu-slug}-container”, a ul tag with a class of “menu”, and then encloses each item inside the menu in li tags with additional classes generated by WP.

This is robust HTML output that is easily customizable with CSS, but if you wish to change the way this code is outputted, you should consult the wp_nav_menu() function reference.

Dynamic Sidebar

Dynamic sidebars support “widgets”. Widgets are chunks of content, interaction, etc. that can be customized by dragging and dropping into dynamic sidebar areas on the back end. WordPress comes packaged with some of its own widgets (such as tag clouds, post categories, etc.) and many plugins also provide widgets.

// Add support for dynamic sidebar
if (function_exists('register_sidebar')) {
	register_sidebar(array(
		'name' => 'Navigation'
	));
}

You may register additional sidebars by repeating the register_sidebar() function and assigning different names. (More information on the register_sidebar() array.)

To display sidebars on the front end, place the following code in your sidebar.php file:

<ul>
	<?php dynamic_sidebar('Navigation') ?>
</ul>

You can also place static content that will be loaded if no dynamic content has been placed, or if widgets are inactive. This can be done like so:

<ul>
	<?php if (!function_exists('dynamic_sidebar') || !dynamic_sidebar() ) : ?>
	<li>Static Content</li>
	<?php endif; ?>
</ul>

By default, the sidebar widgets will output a container li with an H2 heading title. You can edit the HTML output by modifying the parameters specified at register_sidebar().

Add Theme Support

Another great use for the functions.php file is adding theme support. The add_theme_support() function allows you to take advantage of some of the optional features WordPress boasts. New WP releases occasionally add new theme features that need to be initialized via the functions.php file if you wish to use them.

Post Thumbnails

Also known as “Featured Images” (this is what the post meta box is titled), post thumbnails are images that “represent” the post and can be displayed in loops. In the past, featured images have been implemented using WordPress’s custom fields capabilities, but now the feature has been built in and can be used via the following functions:

// Add support for Featured Images
if (function_exists('add_theme_support')) {
	add_theme_support('post-thumbnails');
	// (name of the thumbnail, width, height, crop mode)
	set_post_thumbnail_size(150, 100, true);	// Default thumbnail for loop.
	add_image_size('featured-single', 400, 600, false);	// The thumbnail in the single post, linking to the full-size image.
}

// Generate link to full-size image
function get_image_url( $image_id, $image_size ) {
	$image = wp_get_attachment_image_src( $image_id, $image_size );
	return $image[0];
}

With these functions, we have now generated a hard-cropped default post thumbnail (150px x 100px), a soft-proportioned large thumbnail (400px x 600px), and a link to the uploaded full-size image file.

To display featured images on the front end, you can modify a few different theme files depending on where you’d like your featured images to show up.

To display the default post thumbnail with a link to the full post in archive, index, search results, or other queried loops, use the following:

<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
	<?php the_post_thumbnail(); ?>
</a>

To display the large thumbnail within a post with a link to view the full-size version, try placing something like this in your single.php file inside the loop, wherever you wish the image to display (normally this is done right above the post content):

<?php if ( has_post_thumbnail() ) :
	$image_id = get_post_thumbnail_id();
	$image_url = get_image_url( $image_id, 'full' );
?>
	<a href="<?php echo $image_url; ?>" title="<?php the_title(); ?> (view larger)"><?php the_post_thumbnail('featured-single'); ?></a>
<?php endif; ?>

Default post thumbnails output with an image class of “attachment-post-thumbnail”. Additional image sizes (like our example “featured-single” image) output with a class of “attachment-{thumbnail-name}”.

Other…

You can also add automatic feed links and post formats with add_theme_support. Most themes benefit from Feed Links, but I feel that Post Formats are a more specialized option and do not qualify as “must-have”s.

Custom Editor Styles

Another exciting new feature is the ability to change the styles of the TinyMCE editor field that WordPress uses to create page and post content. This helps to bridge the gap between what you put into the editor and what you see on your site, making it more of a true “What You See Is What You Get” experience.

To enable this functionality, add the following to your functions.php file:

// Add support for TinyMCE custom editor stylesheet
if (function_exists('add_editor_style')) { add_editor_style( 'editor-style.css' ); }

To display editor styles, you now need to add a stylesheet to your theme’s root folder called editor-style.css. Add any styles that you want to show up in the WYSIWYG editor.

Change the Excerpt [...] to a Permalink

When you use the_excerpt(), content that exceeds the excerpt maximum length will be cut off and replaced with [...]. This is not a link, it is simply an indicator that more content exists.

If you wish to use the_excerpt and would like the [...] converted into a permalink to the full post, you can add the following to your functions.php file:

// Replace excerpt [...] with permalink 
function replace_excerpt($content) {
	return str_replace('[...]',
		'<a class="more-link" href="'. get_permalink() .'">read more &raquo;</a>',
			$content
	);
}
add_filter('the_excerpt', 'replace_excerpt');

Custom Comments Callback

By default, WordPress generates the HTML for displaying comments. However, theme-makers frequently wish to modify this code to their own liking. This can be done by adding a custom callback to the wp_list_comments() function.

Add your customized comment HTML to your functions.php file:

// Custom callback for threaded comments to permit HTML editing
function cc_callback($comment, $args, $depth) {
	$GLOBALS['comment'] = $comment; ?>
		<li id="li-comment-<?php comment_ID() ?>" <?php comment_class(); ?>>
			<div id="comment-<?php comment_ID(); ?>" class="the-comment">
			<div class="comment-author vcard">
				<?php echo get_avatar($comment,$size='36',$default='<path_to_url>' ); ?>
				<?php printf(__('<cite class="fn">%s</cite> <span class="says">says:</span>'), get_comment_author_link()) ?>
			</div>
			
	<?php if ($comment->comment_approved == '0') : ?>
		<em><?php _e('Your comment is awaiting moderation.') ?></em>
		<br />
	<?php endif; ?>

	<div class="comment-meta commentmetadata">
		<a href="<?php echo htmlspecialchars(get_comment_link( $comment->comment_ID )) ?>">
		<?php printf(__('%1$s at %2$s'), get_comment_date(),get_comment_time()) ?></a><?php edit_comment_link( __( '(Edit)' ), ' ' ); ?>
	</div>
	
	<?php comment_text() ?>
	
	<?php if($args['max_depth']!=$depth) { ?>
		<div class="reply">
			<?php comment_reply_link(array_merge($args, array('depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
		</div>
	<?php } ?>
	</div>

Edit the HTML to your liking. Do not close the li at the end, as WordPress does this for you to accommodate nested list elements for threaded comments, etc.

To display your custom callback, open your theme’s comments.php file and change wp_list_comments() to use the callback:

<ol class="commentlist">
	<!-- Utilizes a callback to enable customization of comment HTML - see functions.php -->
	<?php wp_list_comments('callback=cc_callback'); ?>
</ol>

Custom Login Logo and Link

This snippet will replace the WordPress login page’s logo with an image you upload to your theme’s /images folder. Keep in mind that the default available dimensions are 326px x 57px, so you will want your logo to be within this size.

Now, the logo will be custom but it’s still linking to wordpress.org. If you’d like to change the URL so that clicking the logo takes you to your site’s homepage, add the following functions:

Custom Post Types and Custom Taxonomies

One of the other great things you can do with functions.php is add support for custom post types and custom taxonomies. However, this is an entire topic unto itself, and has been covered in two other posts: Custom Post Types & Taxonomies and Custom Post Types, revisited.

Final Notes

You should avoid modifying WordPress’s core files. The functions.php file should always be used instead. This way, your changes will not affect or compromise the entire installation. When WordPress updates, your changes will not be overwritten.

Browse the web and the WordPress Codex to find out what else you can do with WordPress functions. The possibilities vastly outstrip anything I could even attempt to cover here.

Happy developing!