Make WordPress Core

Opened 6 weeks ago

Closed 5 days ago

#64465 closed enhancement (duplicate)

Add locate_template_paths filter to allow extending template resolution paths

Reported by: lucascarvalhopl's profile lucascarvalhopl Owned by:
Milestone: Priority: normal
Severity: major Version: trunk
Component: Themes Keywords: has-patch has-unit-tests
Focuses: template Cc:

Description

The locate_template() function currently searches for templates in a fixed and hard-coded set of locations (child theme, parent theme, and theme-compat). While this works well for the default theme hierarchy, it does not provide a way for themes or plugins to participate in the template *resolution process* itself.

A practical use case is a setup where:

  • A site uses a third-party parent theme that cannot be modified.
  • Child themes are developed for different clients with several template parts shared across them.
  • get_template_part() is used extensively to load reusable template fragments.

Without a way to extend the template lookup paths, the only option today for this shared template parts is to copy the files into every child theme, which leads to unnecessary duplication and higher maintenance cost.

This proposal introduces a new filter that allows developers to modify the list of template paths *before* the lookup occurs, without altering the existing template hierarchy.

Example:

<?php
add_filter( 'locate_template_paths', function( $paths ) {
    // Insert shared default templates after the child theme path.
    $custom_path = WP_CONTENT_DIR . '/themes/shared-default/templates/';
    array_splice( $paths, 1, 0, array( $custom_path ) );

    return $paths;
} );

With this approach:

  • get_template_part() and related APIs can resolve template parts from a shared default location.
  • No existing themes or plugins are affected unless they explicitly opt in.
  • This does not overlap with template_include, which operates at a different stage and does not affect template part resolution.

Change History (5)

This ticket was mentioned in PR #10674 on WordPress/wordpress-develop by @lucascarvalhopl.


6 weeks ago
#1

This change introduces a new filter to the locate_template() function that allows themes and plugins to participate in the template *resolution process* by modifying the list of template lookup paths before the lookup occurs.

Currently, locate_template() searches for templates in a fixed set of predefined locations (child theme, parent theme, and theme-compat). While this behavior works well for the default theme hierarchy, it does not provide a mechanism for extending the lookup paths in a controlled and predictable way.

The added filter makes it possible to reuse shared template parts across multiple themes without duplicating files. A common use case is a setup where a site uses a third-party parent theme, multiple client-specific child themes, and a shared default set of template parts maintained by the project. With this change, the lookup order can remain fully predictable (child theme → shared defaults → parent theme → core fallback) while preserving the existing behavior.

This update does not alter the default template hierarchy or behavior. Themes and plugins are unaffected unless they explicitly opt in by using the new filter.

Unit tests are included to verify that template paths can be extended while maintaining backward compatibility.

#2 @westonruter
6 weeks ago

  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from new to closed

Hello! This looks to be a duplicate of #13239. Please propose your patch there, and see if there is already a similar one present.

#3 @lucascarvalhopl
4 weeks ago

  • Resolution duplicate deleted
  • Status changed from closed to reopened

Hi folks,

I understand why this ticket was marked as a duplicate of #13239, since it addresses the same underlying issue. However, I’d like to clarify an important distinction.

Ticket #13239 was opened over 16 years ago (WordPress 3.x era) and, despite multiple reports and confirmations from users over the years, it never progressed to an actual implementation. Its last activity was more than two years ago, which effectively leaves the issue unresolved and stalled.

This ticket is not a re-report of the problem, but rather a concrete and working solution for it.

The accompanying PR:

  • Implements a functional fix for the issue described in #13239
  • Includes automated tests
  • Follows current WordPress coding standards and best practices
  • Is compatible with current WordPress version

In other words, this is the missing piece that #13239 never reached: a real, reviewed, and test-covered implementation that can finally close a long-standing issue affecting many users.

Closing this as a duplicate without evaluating the proposed solution effectively keeps the original problem unresolved, despite the fact that it is now demonstrably solvable.

I’d kindly ask that the PR be reviewed on its technical merits, either by reopening this ticket or by explicitly linking and evaluating the implementation within #13239, so we can finally move this forward and resolve the issue for good.

Thanks for your time and for maintaining WordPress core.

#4 @westonruter
4 weeks ago

  • Milestone set to Awaiting Review

I still think the other ticket is where this conversation should be held.

I'll let someone else decide.

#5 @poena
5 days ago

  • Milestone Awaiting Review deleted
  • Resolution set to duplicate
  • Status changed from reopened to closed

Duplicate of #13239.

I agree that the conversation should be kept in the oldest ticket, not only to preserve the ticket history. Otherwise contributors, including the reporter, needs to keep track of two separate tickets and go back and forward between them.

Note: See TracTickets for help on using tickets.