Как получить ID страницы, поста, рубрики и произвольного типа записи в WordPress
За 15 лет работы с WordPress эта задача всплывает постоянно — то нужно вывести произвольные поля для конкретной страницы, то навесить стиль по ID, то отфильтровать вывод в шаблоне. Ниже — все рабочие способы без воды, сразу к делу.
1. ID главной страницы WordPress
<?php $frontpage_id = get_option(‘page_on_front’); ?>
2. Внутри цикла (The Loop)
Классика:
1
2
3
4
5
6 if ( have_posts() ) {
while ( have_posts() ) {
the_post();
$id = get_the_ID();
}
}
1 | get_the_ID() |
работает только внутри Loop или там, где выставлен глобальный
1 | $post |
. Вне цикла вернёт
1 | null |
.
3. Вне цикла, через глобальный объект
1
2 global $post;
$id = $post->ID;
Работает на одиночных шаблонах (
1 | single.php |
,
1 | page.php |
), но не гарантирован на архивах, где
1 | $post |
может указывать не на то, что ожидаешь. Для архивов используй следующий способ.
4. get_queried_object_id()
Универсальная функция, которая знает, что сейчас «запрошено» — страницу, пост, рубрику, автора, дату:
1 $id = get_queried_object_id();
- на
1single.php
— ID поста;
- на
1page.php
— ID страницы;
- на
1category.php
— ID рубрики;
- на
1author.php
— ID автора;
- на
1tag.php
— ID метки.
Это то, что я использую в 90% случаев в
1 | functions.php |
, когда нужно определить контекст без привязки к конкретному типу записи.
5. ID главной страницы и страницы блога
Отдельная больная тема, потому что
1 | is_front_page() |
и
1 | is_home() |
путают многих.
1
2 $front_page_id = get_option( 'page_on_front' );
$posts_page_id = get_option( 'page_for_posts' );
Работает только если в Настройки → Чтение выставлено «Статическая страница». Если на главной — лента постов,
1 | page_on_front |
будет пустым (0).
6. По слагу (slug) или по заголовку
Если известен URL-адрес (slug), но не ID:
1
2 $page = get_page_by_path( 'about-us' ); // slug страницы
$id = $page ? $page->ID : 0;
С WordPress 6.2
1 | get_page_by_path() |
и
1 | get_page_by_title() |
официально задепрекейчены на прямое использование в пользу
1 | WP_Query |
. Рабочий вариант без депрекейт-варнингов:
1
2
3
4
5
6
7
8 $query = new WP_Query( array(
'name' => 'about-us',
'post_type' => 'page',
'post_status' => 'publish',
'numberposts' => 1,
) );
$id = $query->have_posts() ? $query->posts[0]->ID : 0;
7. По URL целиком
Если есть полный адрес страницы (например, распарсили ссылку из текста):
1 $id = url_to_postid( 'https://site.ru/about-us/' );
Функция сама разберёт rewrite-правила и вернёт ID поста/страницы. Возвращает
1 | 0 |
, если не нашла соответствие.
8. ID рубрики / метки / произвольной таксономии
По названию или слагу:
1
2 $term = get_term_by( 'slug', 'news', 'category' ); // или 'name', 'term_id'
$id = $term ? $term->term_id : 0;
Для меток то же самое, меняешь третий параметр на
1 | post_tag |
, для кастомной таксономии — на её слаг.
Устаревшая, но ещё встречающаяся в легаси-коде функция:
1 $id = get_cat_ID( 'Новости' ); // работает только с категориями, ищет по точному названию
Внутри архива таксономии:
1 $id = get_queried_object_id(); // как в пункте 4
9. ID произвольного типа записи (Custom Post Type)
Никакой магии — все функции выше работают одинаково для CPT, просто добавляй
1 | post_type |
:
1
2
3
4
5
6
7 $query = new WP_Query( array(
'post_type' => 'portfolio',
'name' => 'project-slug',
'numberposts' => 1,
) );
$id = $query->have_posts() ? $query->posts[0]->ID : 0;
Или через
1 | get_posts() |
, если не нужен полный объект
1 | WP_Query |
:
1
2
3
4
5
6
7 $posts = get_posts( array(
'post_type' => 'portfolio',
'name' => 'project-slug',
'posts_per_page' => 1,
) );
$id = $posts ? $posts[0]->ID : 0;
10. По произвольному полю (meta)
Когда ID неизвестен, но известно значение мета-поля:
1
2
3
4
5
6
7
8 $posts = get_posts( array(
'post_type' => 'any',
'meta_key' => 'sku',
'meta_value' => 'ABC-123',
'numberposts' => 1,
) );
$id = $posts ? $posts[0]->ID : 0;
Учитывай, что
1 | meta_value |
без индекса на больших базах — это full scan таблицы
1 | wp_postmeta |
. На проекте с десятками тысяч записей лучше сделать отдельную таблицу или использовать
1 | meta_query |
с явным типом сравнения, но чуда это не даст — узкое место в структуре
1 | wp_postmeta |
, а не в коде.
11. Через REST API
Если работаешь с фронтом на JS или дергаешь WP как headless:
1
2
3 GET /wp-json/wp/v2/pages?slug=about-us
GET /wp-json/wp/v2/posts?slug=my-post
GET /wp-json/wp/v2/categories?slug=news
В ответе — массив объектов,
1 | id |
берёшь из первого элемента. Для кастомных типов эндпоинт будет
1 | /wp-json/wp/v2/{post_type_rest_base} |
.
12. Напрямую из базы (когда php-контекста нет)
Иногда проще дернуть SQL — например, в миграционном скрипте:
1 SELECT ID FROM wp_posts WHERE post_name = 'about-us' AND post_type = 'page';
Для терминов:
1
2
3
4 SELECT t.term_id
FROM wp_terms t
JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
WHERE t.slug = 'news' AND tt.taxonomy = 'category';
Через
1 | wpdb |
в коде плагина/темы:
1
2
3
4
5
6 global $wpdb;
$id = $wpdb->get_var( $wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_name = %s AND post_type = %s",
'about-us',
'page'
) );
Обязательно через
1 | $wpdb->prepare() |
— без этого получаешь SQL-инъекцию на ровном месте.
Частые грабли
-
1get_the_ID()
вне Loop
возвращает1null— типичная причина «функция не работает», хотя на самом деле контекст не тот.
- Page ID vs Front Page ID — если на сайте на главной статическая страница,
1is_front_page()
истинно, но
1get_queried_object_id()всё равно вернёт корректный ID этой страницы, а не 0. Путаница чаще в обратную сторону: когда на главной лента постов,
1get_option('page_on_front')вернёт 0, и это нормально.
-
1get_page_by_title()
ищет по неточному совпадению
в старых версиях WP (до депрекейта) — можно словить не ту запись, если заголовки похожи. Работайте через slug, а не через title, где это возможно. - Кэш объектов. Если правите базу напрямую (SQL), а потом сразу дергаете
1get_post()
— можете получить закэшированные старые данные. Чистите object cache (
1wp_cache_flush()) при отладке.