Как переместить файлы шаблона страницы, такие как page- {slug} .php, в подкаталог?

10

Я хочу переместить файлы шаблонов страниц, например, page-{slug}.phpв подкаталог в моей теме, чтобы WordPress распознавал их автоматически. Если шаблоны страниц указанной формы не существуют в подкаталоге, WordPress должен вернуться к правилам загрузки шаблонов по умолчанию. Как я могу этого достичь?

Примечание-1: Этот вопрос и соответствующие ответы являются более общими для шаблонов страниц, и эта ссылка упоминает template-parts/page, что не одно и то же.

Примечание-2: у меня есть несколько page-{slug}.phpпохожих файлов шаблонов страниц, поэтому я хочу переместить их в подкаталог для более аккуратной организации файлов.

manifestor
источник
2
Возможно, стоило бы поменять их на шаблоны страниц вместо page-slug.php? Core поддерживает наличие шаблонов страниц в подкаталоге: nacin.com/2012/03/29/…
WebElaine

Ответы:

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.phpи index.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файле. Так что, когда$typeестьpage, фильтр-хук становитсяpage_template_hierarchy.

Теперь для нашей цели мы вставим sub-directory/page-{slug}.phpимя файла непосредственно перед тем, как page-{slug}.phpв массив иерархии шаблонов передается функции обратного вызова hooks. Таким образом, WordPress загрузит sub-directory/page-{slug}.phpфайл, если он существует, в противном случае он будет следовать обычной иерархии загрузки шаблонов страниц. Конечно, для обеспечения согласованности мы будем отдавать Custom Page Templateболее высокий приоритет по сравнению с нашим sub-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в вашем pluginsкаталоге WordPress :

<?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файл шаблона и т. Д. (То есть иерархию шаблонов страницы по умолчанию).

Fayaz
источник