Custom templating allows developers to control every aspect of how queries are displayed.
The Loop
The output of any custom query can be templated easily. By default, there is a few built in templates that will work out of the box with any theme. However, a certain amount of styling may be required. The real power is in the ability to define and use custom templates, as well as redefine how the default templates behave.
The templates are based on the default loop. The default loop is included after the template files, and contains all of the actions necessary for virtually any type of output. However, the inclusion of the default loop can be disabled using the wp_query_include_loop filter.
The default loop uses the normalized template name to define each action. The template name is normalized by replacing .php, spaces, dashes, and slashes with underscores. So a template specified as "My Custom Template" produces the action "my_custom_template". A template specified as "includes/my-custom-template.php" will produce the action "includes_my_custom_template".
An example template that outputs an ordered list, with post titles and a link. Since the template is included for each instance of the shortcode, it's important to wrap each function in a function_exists check. Otherwise multiple instances of the same template could cause errors.
/** * Template name: My Custom Template *//** * Open the unordered list */if( !function_exists('my_custom_template_before_while') ) {functionmy_custom_template_before_while( $template_name, $context, $query, $atts ) {echo'<ul class="my-custom-list">'; }add_action('wp_query_before_my_custom_template_while','my_custom_template_before_while',10,4);}/** * Output the content for each post */if( !function_exists('my_custom_template_content') ) {functionmy_custom_template_content( $template_name, $context, $query, $atts ) {printf('<li><a href="%s">%s</a></li>', get_the_permalink(), get_the_title()); }add_action('wp_query_my_custom_template_content','my_custom_template_content',10,4);}/** * Close the unordered list */if( function_exists('my_custom_template_after_while') ) {functionmy_custom_template_after_while( $template_name, $context, $query, $atts ) {echo'</ul>'; }add_action('wp_query_after_my_custom_template_while','my_custom_template_after_while',10,4);}
Custom Loop
An example of a template using a custom loop, instead of the default loop. Some developers may be more comfortable with this more familiar syntax.