New Functions, Hooks, and Behaviour for Theme Developers in WordPress 4.7

WordPress 4.7 introduces some new goodies for theme developers. These changes make powerful new functionality available to themes and plugins. It would be great to see theme developers testing this functionality and providing feedback here in the comments or on the individual tickets linked below.

The get_theme_file_uri() Function, and Friends

#18302

The get_template_part() function, introduced way back in WordPress 3.0, is a fundamental one to theme developers and child theming. The function looks in the child themeChild theme A Child Theme is a customized theme based upon a Parent Theme. It’s considered best practice to create a child theme if you want to modify the CSS of your theme. https://developer.wordpress.org/themes/advanced-topics/child-themes/. for the specified file, and falls back to the parent theme if the file doesn’t exist. This allows a template part to be easily overridden by a child theme, simply by means of the file existing.

The new get_theme_file_uri() function introduced in WordPress 4.7 enables this child theme behaviour for theme file URLs, for example when a CSSCSS Cascading Style Sheets. or JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. file is enqueued. Here’s an example of its use:

wp_enqueue_script( 'my-script', get_theme_file_uri( 'js/my-script.js' ) );

The above code enqueues the URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org of the js/my-script.js file from the child theme if it exists, falling back to the URL of the file in the parent theme. Now your parent theme can enable each of its enqueued assets to easily be overridden by a child theme. And of course, if no child theme is in use then the function simply uses the parent theme URL, just like get_template_part().

The companion function get_theme_file_path() has also been introduced. This is the file path equivalent of get_theme_file_uri(). One use case for this function is if you like to dynamically generate the version parameter for your enqueued assets based on the last modified timestamp of the file (using filemtime()). You can continue to do so by using this function:

wp_enqueue_script(
	'my-script',
	get_theme_file_uri( 'js/my-script.js' ),
	array(),
	filemtime( get_theme_file_path( 'js/my-script.js' ) )
);

Finally, get_parent_theme_file_uri() and get_parent_theme_file_path() are also introduced, which specifically reference the file URL or file path to the file in the parent theme (and regardless of whether or not the file exists). For consistency, these functions can be used as replacements for when you may have otherwise used get_template_directory_uri() and get_template_directory() respectively.

The {$type}_template_hierarchy FilterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.

#14310

This new dynamically-named filter allows the complete template hierarchy of a given request type to be filtered by a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party or theme. Although it’s technically possible for the template hierarchy to be filtered using the existing template_include filter, this new filter allows it to be done in a much more clean, simple, and future-proof way, and without the need to reimplement the entire hierarchy logic within the filter’s callback function.

The filter names available by default are:

  • embed_template_hierarchy
  • 404_template_hierarchy
  • search_template_hierarchy
  • frontpage_template_hierarchy
  • home_template_hierarchy
  • taxonomy_template_hierarchy
  • attachment_template_hierarchy
  • single_template_hierarchy
  • page_template_hierarchy
  • singular_template_hierarchy
  • category_template_hierarchy
  • tag_template_hierarchy
  • author_template_hierarchy
  • date_template_hierarchy
  • archive_template_hierarchy
  • paged_template_hierarchy
  • index_template_hierarchy

Here’s an example of the usage of this new filter to add a year-based file to the top of the hierarchy for date archives:

add_filter( 'date_template_hierarchy', function( array $templates ) {
	$year = get_query_var( 'year' );
	array_unshift( $templates, "year-{$year}.php" );
	return $templates;
} );

Here’s a slightly more complex example of adding a file to the hierarchy for a categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. archive based on the value of its term metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. field:

add_filter( 'category_template_hierarchy', function( array $templates ) {
	$format = get_term_meta( get_queried_object_id(), 'format', true );
	if ( $format ) {
		$new = "category-format-{$format}.php";
		$pos = array_search( 'category.php', $templates );
		array_splice( $templates, $pos, 0, $new );
	}
	return $templates;
} );

More usage examples can be seen in the comment thread on the ticketticket Created for both bug reports and feature development on the bug tracker.: #14310.

This filter also allows debugging plugins to access and display the complete template hierarchy for each request, so you can see which files WordPress is looking for in your theme. The latest version of Query Monitor already supports this functionality.

It’s important to remember that the consistency of the template hierarchy in WordPress is what makes standardised theme structures possible. It’s highly recommended that you do not remove templates from the candidate hierarchy using these new filters, unless you’re absolutely certain of what you’re doing.

Simpler Template Names for Content with Non-ASCII Slugs

#37655

Given a post or term with a non-ASCII name, such as hello-world-😀, the URL-encoded form of the name is used in the template hierarchy. For example, on the single post view the hierarchy looked like this prior to WordPress 4.7:

  • single-post-hello-world-%f0%9f%98%80.php
  • single-post.php
  • single.php
  • singular.php
  • index.php

This isn’t very user-friendly, so WordPress 4.7 adds a new, higher priority template to the hierarchy which uses the non-encoded form of the name:

  • single-post-hello-world-😀.php
  • single-post-hello-world-%f0%9f%98%80.php
  • single-post.php
  • single.php
  • singular.php
  • index.php

This makes it much clearer what a template file refers to when building templates for specific posts or terms that include non-ASCII characters in their name.

#4-7, #dev-notes