如何将页面模板文件(如page- {slug} .php)移动到子目录?


10

我想将页面模板文件移动page-{slug}.php到主题中的子目录中,以使WordPress自动识别它们。如果子窗体中不存在上述表单的页面模板,则WordPress应该退回到默认模板加载规则。我该如何实现?

注意-1: 对于页面模板,问题和相应的答案更为通用,并且链接提到template-parts/page,这不是一回事。

注意2:我有多个page-{slug}.php类似的页面模板文件,因此我想将它们移到子目录中以使文件组织更整洁。


2
也许值得将它们更改为页面模板而不是page-slug.php?核心支持在子目录中包含页面模板:nacin.com/2012/03/29/…–
WebElaine

Answers:


12

页面模板的加载方式:

根据默认的WordPress模板层次结构page请求将根据优先级和命名加载模板,如下所述:

  1. Custom Page Template:如果在页面编辑器中定义。
  2. page-{slug}.php
  3. page-{url-encoded-slug}.php:仅用于多字节字符。
  4. page-{id}.php
  5. page.php
  6. singular.php
  7. index.php

其中,singular.phpindex.php不是真正的页面模板。singular.php是任何单个帖子类型index.php的后备模板,并且是WordPress模板应该加载的任何内容的最终后备模板。因此,前五个是页面模板。

如何从层次结构内的子目录中注入模板文件:

WordPress核心功能会get_page_template()生成必要的page模板层次结构数组,并且在确定要从层次结构中确切加载哪个模板文件之前,WordPress会触发page_template_hierarchy过滤器挂钩。因此,添加子目录的最佳方法是WordPress page-{slug}.php自动在其中查找模板,该方法是使用此过滤器并相对于页面模板层次结构数组中的子目录注入适当的文件名。

注意:原始过滤器挂钩是一个动态过滤器挂钩,定义为{$type}_template_hierarchy,位于wp-includes/template.php文件中。因此,当为$typeis时page,过滤器挂钩变为page_template_hierarchy

现在,出于我们的目的,我们将在传递给hooks回调函数的模板层次结构数组中注入sub-directory/page-{slug}.php文件名page-{slug}.php。这样,WordPress将加载sub-directory/page-{slug}.php文件(如果存在),否则它将遵循常规页面模板加载层次结构。当然,为了保持一致性,Custom Page Templatesub-directory/page-{slug}.php文件相比,我们仍将赋予更高的优先级。因此,修改后的页面模板层次结构将变为:

  1. Custom Page Template:如果在页面编辑器中定义。
  2. sub-directory/page-{slug}.php
  3. sub-directory/page-{url-encoded-slug}.php:仅用于多字节字符。
  4. page-{slug}.php
  5. page-{url-encoded-slug}.php:仅用于多字节字符。
  6. page-{id}.php
  7. page.php

样本functions.php代码:

如果计划仅对单个主题进行此更改,则可以在活动主题的functions.php文件中使用以下代码:

// defining the sub-directory so that it can be easily accessed from elsewhere as well.
define( 'WPSE_PAGE_TEMPLATE_SUB_DIR', 'page-templates' );

function wpse312159_page_template_add_subdir( $templates = array() ) {
    // Generally this doesn't happen, unless another plugin / theme does modifications
    // of their own. In that case, it's better not to mess with it again with our code.
    if( empty( $templates ) || ! is_array( $templates ) || count( $templates ) < 3 )
        return $templates;

    $page_tpl_idx = 0;
    if( $templates[0] === get_page_template_slug() ) {
        // if there is custom template, then our page-{slug}.php template is at the next index 
        $page_tpl_idx = 1;
    }

    $page_tpls = array( WPSE_PAGE_TEMPLATE_SUB_DIR . '/' . $templates[$page_tpl_idx] );

    // As of WordPress 4.7, the URL decoded page-{$slug}.php template file is included in the
    // page template hierarchy just before the URL encoded page-{$slug}.php template file.
    // Also, WordPress always keeps the page id different from page slug. So page-{slug}.php will
    // always be different from page-{id}.php, even if you try to input the {id} as {slug}.
    // So this check will work for WordPress versions prior to 4.7 as well.
    if( $templates[$page_tpl_idx] === urldecode( $templates[$page_tpl_idx + 1] ) ) {
        $page_tpls[] = WPSE_PAGE_TEMPLATE_SUB_DIR . '/' . $templates[$page_tpl_idx + 1];
    }

    array_splice( $templates, $page_tpl_idx, 0, $page_tpls );

    return $templates;
}
add_filter( 'page_template_hierarchy', 'wpse312159_page_template_add_subdir' );

样本插件:

如果要在多个主题中遵循相同的模板文件组织,则最好将此功能与主题分开。在这种情况下,functions.php您无需使用上述示例代码修改主题文件,而是需要使用相同的示例代码创建一个简单的插件。

使用文件名(例如page-slug-template-subdir.php在WordPress plugins目录中)保存以下CODE :

<?php
/*
Plugin Name:  WPSE Page Template page-slug.php to Sub Directory
Plugin URI:   https://wordpress.stackexchange.com/a/312159/110572
Description:  Page Template with page-{slug}.php to a Sub Directory
Version:      1.0.0
Author:       Fayaz Ahmed
Author URI:   https://www.fayazmiraz.com/
*/

// defining the sub-directory so that it can be easily accessed from elsewhere as well.
define( 'WPSE_PAGE_TEMPLATE_SUB_DIR', 'page-templates' );

function wpse312159_page_template_add_subdir( $templates = array() ) {
    // Generally this doesn't happen, unless another plugin / theme does modifications
    // of their own. In that case, it's better not to mess with it again with our code.
    if( empty( $templates ) || ! is_array( $templates ) || count( $templates ) < 3 )
        return $templates;

    $page_tpl_idx = 0;
    if( $templates[0] === get_page_template_slug() ) {
        // if there is custom template, then our page-{slug}.php template is at the next index 
        $page_tpl_idx = 1;
    }

    $page_tpls = array( WPSE_PAGE_TEMPLATE_SUB_DIR . '/' . $templates[$page_tpl_idx] );
                                                                                  uded in the
    // page template hierarchy just before the URL encoded page-{$slug}.php template file.
    // Also, WordPress always keeps the page id different from page slug. So page-{slug}.php will
    // always be different from page-{id}.php, even if you try to input the {id} as {slug}.
    // So this check will work for WordPress versions prior to 4.7 as well.
    if( $templates[$page_tpl_idx] === urldecode( $templates[$page_tpl_idx + 1] ) ) {
        $page_tpls[] = WPSE_PAGE_TEMPLATE_SUB_DIR . '/' . $templates[$page_tpl_idx + 1];
    }

    array_splice( $templates, $page_tpl_idx, 0, $page_tpls );

    return $templates;
}
// the original filter hook is {$type}_template_hierarchy,
// wihch is located in wp-includes/template.php file
add_filter( 'page_template_hierarchy', 'wpse312159_page_template_add_subdir' );

用法:

使用以上任一代码,WordPress都会自动识别主题目录中的page-{slug}.php模板文件page-templates

举例来说,您有一个about页面。因此,如果没有custom page template来自编辑器的设置,则WordPress将寻找THEME/page-templates/page-about.php模板文件,如果不存在,则WordPress将寻找THEME/page-about.php模板文件,依此类推(即默认页面模板层次结构)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.