WordPress

Themes

  • A Theme defines the presentation or theming layer of the WordPress application.
  • Many themes can be installed but only one can be active at a time. Themes are activated from within the WordPress admin panel.
  • All files for each installed theme reside in their own directory in /wp-content/themes/.
  • WordPress includes a default theme. Examine the files in the default theme for working examples.
  • A theme must have at least the stylesheet file style.css and the index.php file present in it’s theme directory to be available in the admin panel.

style.css

/wp-content/themes/{my_theme}/style.css
The style.css file should start with a comment block containing data about the theme.

/*
Theme Name: WattsWork
Theme URI: https://github.com/daniel-watts/dev.wattswork.wordpress.theme
Author: Daniel Watts
Author URI: http://wattswork.com/
Description: A responsive WordPress theme designed for the "dev.wattswork.com" website. Open for public use.
Version: 1.3
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: wattswork, minimal
Text Domain: wattswork
*/

index.php

  • File location: /wp-content/themes/{my_theme}/index.php
  • The file is the default template file for the theme and is required for the theme to work.
  • All other template files fall-back the file.
  • Including of template partial files should mostly happen here.
/**
 * The main WattsWork Theme WP template file.
 *
 * @package WordPress
 * @subpackage WattsWork
 */

functions.php

/wp-content/themes/{my_theme}/functions.php
The functions.php file is the default fall-back file for every request and is where template logic and file includes for the theme should take place.

/**
 * The WattsWork Theme WP functions file.
 *
 * @package WordPress
 * @subpackage WattsWork
 */

Theme Features

Theme Features are functionality that may be optionally added to a theme. Themes must register each individual Theme Feature. Registration functions should be called in the theme’s functions.php file. Most often adding functionality means you get an editable field in the admin page for the post, and you can use feature-specific methods to pull data into your theme.

These are the theme features currently available:

Feature Registered with Description
Post Thumbnails add_theme_support('post-thumbnails') An image that is chosen as the representative image for Posts, Pages or Custom Post Types. The display of this image is up to the theme.
Sidebars register_sidebar($args) A vertical column provided by a theme for displaying information other than the main content of the web page. Sidebars usually contain widgets that an administrator of the site can customize.
Navigation Menus register_nav_menus() Add customizable navigation menus to a theme. Using menus requires adding display code to theme files.
Theme Markup add_theme_support('html5', $args) Allows themes to explicitly choose to apply HTML5 markup for search forms, comment forms, comment lists, gallery and caption. The second parameter accepts one or more values indicating which HTML5 features to support and is a required parameter for forward compatibility reasons.
Title Tag add_theme_support('title-tag') Allows themes to use future-proofed title tags in the HTML <head> tag.
Custom Headers add_theme_support('custom-header') A custom header is an image that is chosen as the representative image in the theme top header section.
Editor Style add_editor_style() Allows links to a custom stylesheet file in the TinyMCE editor within the post edit screen.
Automatic Feed Links add_theme_support('automatic-feed-links') Adds RSS feed links to HTML <head> tag.
Content Width $content_width = 600; Set the maximum allowed width for any content in the theme, like oEmbeds and images added to posts.
Custom Backgrounds add_theme_support('custom-background') Provides for customization of the background color and image.
Post Formats add_theme_support('post-formats', array('{format name}')) An admin can change how each post looks by choosing a Post Format from a radio-button list in the Publish meta box when saving a post. Options are aside, gallery, link, image, quote, status, video, audio, chat
Theme Logo add_theme_support('custom-logo') Allows themes to add custom logos.
Selective Refresh Support for Widgets add_theme_support('customize-selective-refresh-widgets') Users of the Customizer can selectively refresh a preview mechanism without refreshing the entire preview window.

Sidebars

Register a sidebar in the theme functions.php file:


function wattsworkmorgue_register_main_sidebar() {
    register_sidebar( array(
        'name' => __('Main Sidebar', 'wattsworkmorgue'),
        'id' => 'main-sidebar',
        'description' => __('Widgets in this area will be shown on all posts and pages.', 'wattsworkmorgue'),
        'before_widget' => '<li id="%1$s" class="widget %2$s">',
        'after_widget'  => '</li>',
        'before_title'  => '<h2 class="widgettitle">',
        'after_title'   => '</h2>',
    ));
}
add_action('widgets_init', 'wattsworkmorgue_register_main_sidebar');

Post Thumbnail

Post Thumbnail, also called the Featured Image, is an image that is chosen as the representative image for a Post, Page or Custom Post Type.

The Post Thumbnails feature can be enabled by calling add_theme_support('post-thumbnails') from the functions.php file of a theme. The default thumbnail size must be defined. Any additional thumb sizes can also be defined.

/**
 * Adds Post Thumbnail support to the theme.
 */
if (function_exists('add_theme_support')) { 
    add_theme_support('post-thumbnails');
    set_post_thumbnail_size(200, 9999); // Set the default thumb size to 200px wide with unlimited height.
    add_image_size('small-admin-thumb', 100, 100, true); // Set an additional thumb size of 50px wide by 50px tall and cropped.
}

NOTE
The Post Thumbnail is associated to the post in the database in the wp_postmeta table.
The associated thumb ID is stored as the meta_value value with a meta_key called _thumbnail_id.

To see the thumbnail which is attached to the post in the admin panel, display the thumb on the

/**
 * Adds a thumbnail column to an admin posts list.
 */
function add_admin_thumbnail_column($post_columns){
    $post_columns['featured_thumb'] = __('Featured Image');
    return $post_columns;
}

// Add a thumbnail column to the `posts` and `pages` admin post lists.
add_filter('manage_posts_columns', 'add_admin_thumbnail_column', 2);
add_filter('manage_pages_columns', 'add_admin_thumbnail_column', 2);

/**
 * Prints the thumbnail column content.
 */
function admin_thumbnail_column_content($column_name, $post_id){
    if ($column_name == 'featured_thumb' && function_exists('the_post_thumbnail')) {
        echo the_post_thumbnail('small-admin-thumb');
    }
}

// Get the content for the thumbnail column in `posts` and `pages` admin post lists.
add_action('manage_posts_custom_column', 'admin_thumbnail_column_content', 5, 2);
add_action('manage_pages_custom_column', 'admin_thumbnail_column_content', 5, 2);

Templates

Template Hierarchy

The WordPress themeing system tries to match a theme file to a specific request. If a specific template file does not exist, the theme falls-back to the next available file (like maybe from the parent theme), and if that is not found, the last fall-back for all template files, the index.php file is used. In WordPress this fall-back method is called the Template Hierarchy.

For instance, if a theme provides a template file called category.php and a category page is being requested, the category.php file will be loaded. If the category.php file is not found, index.php is used as usual.

More Resources

Here are some diagrams meant to illustrate the file override paths of the Template Hierarchy:

WordPress-Theme-Template-Hierarchy

WordPress-Theme-Template-Hierarchy-Detail

Template Files

Template files are PHP files used to render web pages for a WordPress theme.

  • Template files can contain a mixture of HTML, WP Template Tags, and PHP code.
  • Template files can include other template files using WP Template Tags.
    When a piece of a page is included into a template file, such as including the header.php file, the include is called a Template Partial. Template Partials can be embedded in multiple template files, simplifying theme creation.

Here is a list of some basic theme templates and files recognized by WordPress:

Filename Description
index.php The main template file. It is required in all themes.
style.css The main stylesheet. It is required in all themes and contains the information header for your theme.
rtl.css The right-to-left stylesheet is included automatically if the website language’s text direction is right-to-left.
comments.php The comments template.
front-page.php The front page template is always used as the site front page if it exists, regardless of what settings on Admin > Settings > Reading.
home.php The home page template is the front page by default. If you do not set WordPress to use a static front page, this template is used to show latest posts.
header.php The header template file usually contains your site’s document type, meta information, links to stylesheets and scripts, and other data.
singular.php The singular template is used for posts when single.php is not found, or for pages when page.php are not found. If singular.php is not found, index.php is used.
single.php The single post template is used when a visitor requests a single post.
single-{post-type}.php The single post template used when a visitor requests a single post from a custom post type. For example, |single-book.php would be used for displaying single posts from a custom post type named book. The index.php is used if a specific |query template for the custom post type is not present.
archive-{post-type}.php The archive post type template is used when visitors request a custom post type archive. For example, |archive-books.php would be used for displaying an archive of posts from the custom post type named books. The archive.php template file is used if the archive-{post-type}.php is not present.
page.php The page template is used when visitors request individual pages, which are a built-in template.
page-{slug}.php The page slug template is used when visitors request a specific page, for example one with the “about” slug (page-about.php).
category.php The category template is used when visitors request posts by category.
tag.php The tag template is used when visitors request posts by tag.
taxonomy.php The taxonomy term template is used when a visitor requests a term in a custom taxonomy.
author.php The author page template is used whenever a visitor loads an author page.
date.php The date/time template is used when posts are requested by date or time.
archive.php The archive template is used when visitors request posts by category, author, or date. Note: this template will be overridden if more specific templates are present like category.php, author.php, and date.php.
search.php The search results template is used to display a visitor’s search results.
attachment.php The attachment template is used when viewing a single attachment like an image, pdf, or other media file.
image.php The image attachment template is a more specific version of attachment.php and is used when viewing a single image attachment. If not present, WordPress will use attachment.php instead.
404.php The 404 template is used when WordPress cannot find a post, page, or other content that matches the visitor’s request.

Template Tags

Template tags are used within themes to include other template files (template partials) and retrieve content from your database. The content could be anything from a blog title to a complete sidebar. Template tags are the preferred method to pull content into your theme files.

WP function File included Default include if file not found
get_header() header-{name}.php wp-includes/theme-compat/header.php
get_footer() footer-{name}.php wp-includes/theme-compat/footer.php
get_sidebar() sidebar-{name}.php wp-includes/theme-compat/sidebar.php
get_search_form() searchform.php WP auto-generated
comments_template() comments.php wp-includes/theme-compat/comments.php
get_template_part() {name}.php Returns nothing

Conditional Tags

WP function Ruturns true if:
is_404() The request returns an “HTTP 404: Not Found” error.
is_admin() The request is for the admin Dashboard or the administration panel.
is_archive() The request is for any type of archive page. An archive can be a Category, Tag, Author, Date, Custom Post Type or Custom Taxonomy based pages.
is_attachment() The request is for an attachment. An attachment is an image or other file uploaded through the post editor’s upload utility. Attachments can be displayed on their own ‘page’ or template.
is_author() The request is for an author archive page.
is_category() The request is for an existing category archive page.
is_home() The request is for the blog homepage.
is_network_admin() The request is for a network admin screen (wp-admin/network).
is_page() The request is for an existing single page.
is_post_type_archive() The request is for an archive page of a given post type(s).
is_search() The request is for the search result page.
is_single() The request is for an existing single post. Works for any post type, except attachments and pages
is_sticky() The current post is a Sticky Post meaning the “Stick this post to the front page” check box has been checked for the post.
is_tag() The request is for a Tag archive page.
is_tax() The request is for a custom taxonomy archive page.

NOTE
When you use is_home() and is_front_page(), you have to use them in the right order to avoid bugs and to test every user configuration:

if ( is_front_page() && is_home() ) {
    // Default homepage
} elseif ( is_front_page() ) {
    // static homepage
} elseif ( is_home() ) {
    // blog page
} else {
    //everything else
}

Post Tags

WP function Use
the_content() Displays the post content HTML.
get_the_content() Returns the raw post content.
An important difference from the_content() is that get_the_content() does not pass the content through the ‘the_content’ filter. This means that get_the_content() will not auto-embed videos or expand shortcodes, among other things.

Conditional Tags

Conditional Tags are WordPress functions which test to see whether a certain condition is met by returning either TRUE or FALSE. Depending on what conditions are met a developer can define what to show and or what template files to include into a page.

Tag True
is_home() When the main blog home page should be displayed. This is the page which shows the time based blog content of your site, so if you’ve set a static Page for the Front Page (see below), then this will only be true on the Page which you set as the “Posts page” in Administration > Settings > Reading.
is_front_page() When the front of the site should be displayed, whether it is posts or a Page. Returns true when the main blog page is being displayed and the ‘Settings > Reading ->Front page displays’ is set to “Your latest posts”, or when ‘Settings > Reading ->Front page displays’ is set to “A static page” and the “Front Page” value is the current Page being displayed.
is_single() When a single post of any post type (except attachment and page post types) is being displayed. This function can get specific. See the docs.
is_page() When any Page (a post with post_type ‘page’) should be displayed.
is_category() A category
is_author() An author
is_date() A year, month, or day
is_year() A year
is_month() A month
is_day() A day
is_time() An hour, minute, or second
is_archive() A category, author, or date
is_search() A search
is_404() A 404 page
is_feed() A syndication feed

Routing with Conditional Tags

WordPress intendeds for you to work with the Template Hierarchy, which is wise if you are working on an extendable theme, but another way of routing template files is to forgo the use of all direct template files and build a theme router which is more organized and centralized.

The WordPress function get_template_part() can be used to include template files from sub-directories making it easier to organize the theme files.
An example of theme routing using conditional tags in the index.php file:

<?php
// Route the request to it's template file.
    if (is_home())   { get_template_part('pages/home'); }
elseif (is_single()) { get_template_part('pages/single'); }
elseif (is_search()) { get_template_part('pages/search'); }
  else               { get_template_part('pages/404'); } // By default everything is a 404 page.
?>

The pages/404.php template file:

<?php get_template_part('partials/doc_head'); ?>
<h1>404 Page Not Found</h1>
<p>Sorry but there is nothing here.</p>
<?php get_template_part('partials/doc_foot'); ?>

Page Titles

# Default value.
$page_title = 'Untitled';

if (is_404()) {
    $page_title = '404 Page Not Found';
} elseif (is_search()) {
    if (get_search_query() == ''){
        $page_title = 'Search Results for Everything';
    } else {
        $page_title = 'Search Results for: "' . get_search_query() . '"';
    }
} elseif (is_home()) {
    $page_title = get_bloginfo('name');
} elseif (is_single() || is_page()) {
    $page_title = get_the_title();
} elseif (is_category()) {
    $page_title = single_cat_title("", false);
} elseif (is_tag()) {
    $page_title = single_tag_title("", false);
} elseif (is_day() ) {
    $page_title = 'Daily Archive ' . get_the_date();
} elseif (is_month()) {
    $page_title = 'Monthly Archive ' . get_the_date('F Y');
} elseif (is_year()) {
    $page_title = 'Yearly Archive ' . get_the_date('Y');
}

Sidebars

Call register_sidebar() for each sidebar you want to create.

# Define the 'main-sidebar'.
add_action( 'widgets_init', 'my_register_sidebars' );
function my_register_sidebars(){

    register_sidebar(
        array(
            'id' => 'main-sidebar',
            'name' => __( 'Main Sidebar' ),
            'description' => __( 'Widgets in this area will be shown on all posts and pages.' ),
            'before_widget' => '<aside id="%1$s" class="widget %2$s">',
            'after_widget' => '</aside>',
            'before_title' => '<h3>',
            'after_title' => '</h3>'
        )
    );

    /* Repeat register_sidebar() code here for each additional sidebar. */
}

Posts

Post types are the different ways a page can be built in WordPress. The most common post type is called the ‘post’, it builds an HTML page with lists of post types. For instance, most WordPress blogs have a homepage which lists the most recent posts, this page has the Post post type.

Post Types

There are five post types available by default in the WordPress:

Type slug
Post post
Page page
Attachement attachment
Revision revision
Post nav_menu_item
Navigation menu post

Additional post-types can be added

Post-Type Features

The add_post_type_support() function enables you to add support for various WordPress features to WordPress post-types. For example, by default the Page post type does not support excerpts, but by using add_post_type_support() you can add support.

add_post_type_support( $pageType,  $featureName );

Custom Admin Fields

Input fields on WordPress add/edit admin screens are called custom fields. Custom field data is called metadata.

Custom fields are displayed inside meta boxes, containers which can be placed on WP add/edit admin screens. When a post is updated, all custom field data is sent along with the post data to be processed server-side.

 

More Resources

Metadata

Custom field values stored in the database are called metadata. Metadata are key-value pairs of data that are attached to WordPress object types (posts, comments, users, terms, etc). Each object type instance is stored respectively as a row in it’s own database table wp_posts, wp_comments, wp_users, etc. Metadata for object types are also stored respectively in their own tables wp_postmeta, wp_commentmeta, wp_usermeta, etc. The only object type in WordPress which does not have metadata is the link.

Metadata tables all have a meta_key and meta_value column as well as a {obj type}_id column to key the metadata entry to the parent post, and an auto-incrementing id column.

Read and Write

The get_post_meta() and update_post_meta() WP functions are used to read and write metadata to the database. Both functions take the parent post ID, the key, and the value as parameters.

NOTE: WordPress has some peculiar behavior around metadata keys. Multiple metadata keys for a post can have the same name.

get_post_meta()

Documentation: developer.wordpress.org

Param Type Req Notes
$post_id int required The Post ID.
$key string optional The name of the meta key to retrieve. By default, returns data for all keys associated to the post. Meta keys are case-sensitive.
Default value: ”
$single bool optional Whether to return a single value.
Default value: false
returns mixed Will be an array of meta key-value pairs if $single is false. Will be the value of the meta data field if $single is true.

Add a Meta Box

To create custom fields a meta box must first be created by calling the add_meta_box() function and defining the post type(s) it should belong to.

The following code can be added to the functions.php file of a theme to create a Settings meta box which will display on the add/edit screens for the post post-type:

/**
 * Add the new `settings` meta box to the 'post' post-type.
 */
function prefix_add_settings_meta_box()
{
    add_meta_box(
        'prefix_post_settings_meta_box', // $id Unique ID of the meta box.
        'Settings', // $title Title of the meta box.
        'prefix_display_post_settings_fields', // $callback Name of the function which displays the meta box fields.
        'post', // $screen Post-type this meta box is assigned-to.
        'normal', // $context
        'high' // $priority
    );
}
add_action('add_meta_boxes', 'prefix_add_settings_meta_box');

// Display the `settings` meta box content.
function prefix_display_post_settings_fields($post, $args)
{
    echo 'Hello!';
}

add_meta_box()

Documentation: developer.wordpress.org

Param Type Req Notes
$id string yes The unique ID for the meta box. (used in the ‘id’ attribute for the meta box).
$title string yes The display title of the meta box. This value can/should be internationalized.
$callback callable yes Name of the function which defines the meta box content. The function should echo its output.
$screen string/array no The post-type ID(s) of the page(s) where the meta box will be displayed. This value can be a single post-type ID, page (screen) ID, WP_Screen object, or an array of IDs.
Default value: null
$context string no Defines the section of the page where the meta box should be placed (normal, advanced, or side). Other contexts vary from screen to screen. Comments screen contexts include ‘normal’ and ‘side’. Menus meta boxes (accordion sections) all use the ‘side’ context.
Default value: ‘advanced’
$priority string no Specifies the order within the section where the meta box will be placed (high, core, default, or low).
Default value: ‘default’
$callback_args array no An array of arguments ($args) that can be passed to the callback function.
Default value: null

Add Fields

The name of a callback function is passed to the add_meta_box() method. The callback function prints the HTML content of the meta box.

/**
 * Prints the `settings` meta box content.
 *
 * @param object $post The current WP post object. Basically the values
 *                     of the `wp_posts` DB table row for the post.
 * @param array  $args Info about the parent meta box as well as any
 *                     callback args passed to the WP `add_meta_box`
 *                     function.
 *
 * @return void
 */
function prefix_display_post_settings_fields($post, $args)
{
    // Get field data from the DB.
    $meta = get_post_meta($post->ID, 'prefix_post_settings_fields', true);

    // Begin the HTML output.
    $html = array();
    
    // Create a hidden nonce field for added security.
    $html[] = '<input type="hidden" name="post_settings_meta_box_nonce" value="' . wp_create_nonce(basename(__FILE__)) . '">';
    
    // Create the label and input field for the `prefix_first_name` field.
    $html[] = '<label for="prefix_post_settings_fields[first_name]">First Name</label>';
    $html[] = '<input type="text" name="prefix_post_settings_fields[first_name]" id="prefix_post_settings_fields[first_name]" class="regular-text" value="' . $this->meta_key($meta, 'first_name') . '">';
    
    // Create the label and input field for the `prefix_last_name` field.
    $html[] = '<label for="prefix_post_settings_fields[last_name]">Last Name</label>';
    $html[] = '<input type="text" name="prefix_post_settings_fields[last_name]" id="prefix_post_settings_fields[last_name]" class="regular-text" value="' . $this->meta_key($meta, 'last_name') . '">';
    
    echo '<pre>';
    print_r($meta);
    echo '</pre>';
    
    // Print the HTML to the screen.
    return print implode("\n", $html);
}

Database

Using the WPDB Class

The wpdb class can be used to execute SQL query statements which return PHP objects
In order to work with the class you have to declare it as a global variable.

global $wpdb;

For OOP I’ve found it best to declare the wpdb object in a custom database class constructor and assign the class to a class property for ease of reuse.

public $wpdb;

public function __construct()
{
    global $wpdb;
    $this->wpdb = $wpdb;
}

Table Names

It is possible to assign prefixes to WordPress database table names. This is done when the WP app is installed. In order to properly work with the WPDB, make sure to append the prefix property from the wpdb object to all table names.

$table_name = $wpdb->prefix . 'posts';
$sql_query = "SELECT * FROM $table_name LIMIT 10";

WP also has built-in table names for working with default tables: $wpdb->posts, $wpdb->postmeta, and $wpdb->users.

Query Helper Methods

WP has built-in helper methods for working with basic database queries: $wpdb->insert(), $wpdb->update(), and $wpdb->get_row().

Using an External Database

To connect to an external database, create a new instance of the wpdb class.

// Connect to an external database.
$extdb = new \wpdb($username, $password, $db_name, $db_host);

// test the new DB object.
if (is_object($extdb) && !isset($extdb->error)) {
    // DB object is good.
}
 

More WP DB Resources


Images

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

Notes

  • Using the ‘false’ setting will fail to produce a new image in the upload directory if one of the image dimensions of the uploaded image are equal to the new image size.
  • If a registered image size is removed from functions.php, then any image uploaded before that point and then deleted from the media library afterwards, does not have those auto-generated sizes deleted too. Only image sizes that exist in functions.php are deleted.

Comments

WordPress Codex: comments_template()

comments_template() loads a comment template. Used primarily in single Post and Page displays, but will work outside of single displays if $withcomments is set to “1”.

Reference Links