Получить ID страницы по шаблону
Когда создаётся страница, назначенный ей шаблон сохраняется как пользовательское поле (метаданные) записи, аналогично другим пользовательским полям. Ключ meta_key
имеет значение _wp_page_template
, а значение meta_value
будет содержать имя файла шаблона страницы.
Вы можете использовать функцию get_pages
для получения всех страниц, у которых в meta_value
указан определённый шаблон:
$pages = get_pages(array(
'meta_key' => '_wp_page_template',
'meta_value' => 'page-special.php'
));
foreach($pages as $page){
echo $page->ID.'<br />';
}
ОБНОВЛЕНИЕ 23-07-2015
Если нужны только ID страниц, лучше использовать функцию get_posts
, указав page
как тип записи (post_type
), а ids
в качестве значения параметра fields
. Это обеспечит более быстрый и оптимизированный запрос, так как из базы данных будет возвращён только столбец с ID записей, а не все данные страниц.
(Требуется PHP 5.4 и выше)
$args = [
'post_type' => 'page',
'fields' => 'ids',
'nopaging' => true,
'meta_key' => '_wp_page_template',
'meta_value' => 'page-special.php'
];
$pages = get_posts( $args );
foreach ( $pages as $page )
echo $page . '</br>';

Привет, спасибо. Не слишком ли это "тяжело"? (перебор всех страниц)

Зависит от количества страниц. На самом деле, я не знаю более быстрого нативного способа получить эти данные. Если у вас много страниц, я бы предложил использовать транзиенты для хранения этих данных и сбрасывать/удалять транзиент только при публикации новой страницы.

@user3800799 Я обновил пост, если вас интересует только получение идентификаторов и больше ничего

Вы также можете использовать set_transient
(https://codex.wordpress.org/Transients_API), если не хотите слишком часто обращаться к базе данных.

@ChrisAndersson Если у вас не сотни страниц, использование transient здесь будет практически бесполезным. Мой код выполняет только один сверхбыстрый запрос к базе данных, так как мы запрашиваем только ID записей, что значительно повышает производительность. Transients выполняют два запроса к базе при каждой загрузке страницы, хотя могут быть чуть быстрее. Transients полезны только для ресурсоемких операций

Если ваш шаблон страницы находится во вложенной папке, например theme-folder/page-templates/page-template.php, то следующий запрос будет работать:
$page_details = get_pages( array(
'post_type' => 'page',
'meta_key' => '_wp_page_template',
'hierarchical' => 0,
'meta_value' => 'page-templates/page-template.php'
));
Приведенный выше код также отображает и дочерние страницы.
Спасибо

Вот полная функция, совместимая с WPML и Polylang. Автор: https://github.com/cyrale/
/**
* Поиск страницы с определённым шаблоном.
*
* @param string $template Имя файла шаблона.
* @param array $args (Опционально) Дополнительные параметры, аналогично get_posts().
* @param bool $single (Опционально) Возвращать одно значение или массив.
*
* @return Будет возвращён массив объектов WP_Post, если $single равен false. Если $single равен true, вернёт объект WP_Post при успешном поиске, иначе FALSE.
*/
if (!function_exists('get_page_by_template')) {
function get_page_by_template($template, $args = array(), $single = true) {
$pages_by_template = wp_cache_get('pages_by_template', 'cyrale');
if (empty($pages_by_template) || !is_array($pages_by_template)) {
$pages_by_template = array();
}
if (!isset($pages_by_template[$template])) {
$args = wp_parse_args(array(
'posts_per_page' => -1,
'post_type' => 'page',
'suppress_filters' => 0,
'meta_query' => array(
array(
'key' => '_wp_page_template',
'value' => $template,
),
),
), $args);
$pages = get_posts($args);
$pages_by_template[$template]= array(
'single' => !empty($pages) && is_array($pages) ? reset($pages) : false,
'pages' => $pages,
);
}
wp_cache_set('pages_by_template', $pages_by_template, 'cyrale');
return $pages_by_template[$template][$single ? 'single' : 'pages'];
}
}

Ниже представлен более детализированный скрипт, который учитывает язык, если это необходимо. ОБРАТИТЕ ВНИМАНИЕ, что он предполагает использование Polylang, а не WPML.
function get_post_id_by_template($template,$lang_slug = null){
global $wpdb;
$wh = ($lang_slug) ? " AND t.slug = %s" : "";
$query = $wpdb->prepare(
"SELECT DISTINCT p.ID
FROM $wpdb->posts p
INNER JOIN $wpdb->postmeta meta ON meta.post_id = p.ID
INNER JOIN $wpdb->term_relationships tr ON meta.post_id = tr.object_id
INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id
WHERE p.post_status = 'publish' AND meta.meta_key = %s AND meta.meta_value = %s" . $wh,
'_wp_page_template',
$template,
$lang_slug
);
$ids = $wpdb->get_results($query);
if($ids && isset($ids[0])){
$p = $ids[0];
return $p->ID;
} else {
return false;
}
}// get_post_id_by_template

function kavkaz_get_page($page_template_filename){
// Получаем страницы с указанным шаблоном
$pages = get_pages( array(
'meta_key' => '_wp_page_template',
'meta_value' => $page_template_filename
) );
$url = null;
// Если страница найдена, получаем её URL
if(isset($pages[0])) {
$url = $pages[0]->guid;
}
// Возвращаем экранированный URL
return esc_url( $url );
}

Это выглядит примерно так же, как два верхних ответа, поиск через get_pages() по meta_key? Я также думаю, что ->guid неверен: он может быть URL, но это не гарантировано. Вместо этого я бы передал объект страницы (или просто ID) в get_permalink().

Ваш ответ можно улучшить, добавив дополнительную подтверждающую информацию. Пожалуйста, [отредактируйте], чтобы добавить больше деталей, таких как ссылки или документация, чтобы другие могли подтвердить правильность вашего ответа. Вы можете найти больше информации о том, как писать хорошие ответы, в справочном центре.
