The core function behind WordPress template loading is load_template(). Its job is to load the template files required by a theme and pass the global variables needed to display WordPress content into those files. That is why global variables are available directly in the main loop. The core code looks like this:
function load_template( $_template_file, $require_once = true ) {
global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
if ( is_array( $wp_query->query_vars ) ) {
extract( $wp_query->query_vars, EXTR_SKIP );
}
if ( isset( $s ) ) {
$s = esc_attr( $s );
}
if ( $require_once ) {
require_once( $_template_file );
} else {
require( $_template_file );
}
}
get_template_part(): A Higher-Level Wrapper Around Template Loading
The get_template_part() function loads templates by using locate_template(). At first glance it may seem like unnecessary wrapping, but in practice it makes template loading much easier for theme developers. It provides a simple fallback mechanism: if a specialized template exists, WordPress loads it; otherwise it falls back to the default one.
function get_template_part( $slug, $name = null ) {
/**
* Fires before the specified template part file is loaded.
*/
do_action( "get_template_part_{$slug}", $slug, $name );
$templates = array();
$name = (string) $name;
if ( '' !== $name )
$templates[] = "{$slug}-{$name}.php";
$templates[] = "{$slug}.php";
locate_template($templates, true, false);
}
get_header(): Template Loading with Hook Support
Many developers assume that get_header() is simply a more advanced version of get_template_part(), but if you read the source you will see that is not quite true. Its most important role is to fire the get_header hook and then load the correct header template.
function get_header( $name = null ) {
/**
* Fires before the header template file is loaded.
*/
do_action( 'get_header', $name );
$templates = array();
$name = (string) $name;
if ( '' !== $name )
$templates[] = "header-{$name}.php";
$templates[] = 'header.php';
if ('' == locate_template($templates, true))
load_template( ABSPATH . WPINC . '/theme-compat/header.php');
}
By default, this function includes header.php, but it also lets you pass a string to load a specialized header file for specific pages. For example, get_header('home') loads header-home.php.
The later functions get_footer() and get_sidebar() follow the same pattern, so I will not repeat them here.
Technically, get_template_part('header') can also load a header template and it even looks like it follows WordPress theme conventions. However, it is still the wrong choice in this situation because it skips do_action( 'get_header', $name );. That can break compatibility with plugins that rely on the hook.
Template Priority and Usage
The get_template_part() function prefers the specialized template file if it exists. If it does not, WordPress falls back to the default template file. For example:
get_template_part('content', 'product')
This will first try to load content-product.php. If that file does not exist, it will load the default content.php.
Why Not Use Plain PHP Includes?
You can absolutely use raw PHP file includes to achieve a similar result, and I have seen good developers do this with include. The problem is that plain PHP includes have no fallback mechanism, so they cannot satisfy WordPress template hierarchy and template-loading priority requirements the way the WordPress helper functions can.
