<? phpukraine СПІВБЕСІДИ
Пошук по платформі
WORDPRESS · JUNIOR ЧАСТО ПИТАЮТЬ

Як працює ієрархія шаблонів WordPress і як її перекрити з child theme?

Після резолву запиту wp-includes/template-loader.php перебирає умовні теги (is_404, is_search, is_front_page, is_home, is_singular, is_archive…) і для першого збігу будує список кандидатів від найконкретнішого до index.php; locate_template() шукає кожного кандидата спершу в child theme, потім у parent, тому перекриття — це файл із такою самою назвою в дочірній темі.

Я поклав у тему файл page-contacts.php, а сторінка «Контакти» все одно рендериться через page.php. Чому?
Який файл теми відповість за URL /category/news/, якщо в темі є index.php, archive.php і category.php?
Чому після оновлення батьківської теми зникли всі мої правки в single.php?
У чому різниця між get_template_directory() і get_stylesheet_directory()?
ієрархія шаблонів child theme template-loader locate_template

Коли WordPress відпрацював WP_Query і знає, що саме запитали, керування отримує wp-includes/template-loader.php. Він послідовно перевіряє умовні теги — is_embed(), is_404(), is_search(), is_front_page(), is_home(), is_post_type_archive(), is_tax(), is_attachment(), is_single(), is_page(), is_singular(), is_category(), is_tag(), is_author(), is_date(), is_archive() — і для першого збігу викликає відповідну get_*_template(). Ця функція не шукає файл сама: вона будує масив імен-кандидатів від найконкретнішого до найзагальнішого і передає його в get_query_template(), а той у locate_template(). Тобто «ієрархія» — це буквально впорядкований масив рядків, і будь-який запит завершується щонайпізніше на index.php, який тому й обовʼязковий для валідної теми.

Конкретність кандидатів рахується від даних поточного обʼєкта. Для одного запису це single-{post_type}-{post_name}.php, single-{post_type}.php, single.php, singular.php, index.php; для сторінки — спершу кастомний шаблон із метаполя _wp_page_template, далі page-{slug}.php, page-{id}.php, page.php, singular.php; для категорії — category-{slug}.php, category-{id}.php, category.php, archive.php. Звідси дві типові пастки джуна: слаг береться з post_name, а не з заголовка, тому сторінка «Контакти» з URL /kontakty/ шукає page-kontakty.php; і ID/слаг беруться саме поточного терміна, без успадкування від батьківської категорії. Окремо стоїть головна: front-page.php перекриває все, а якщо його немає, вибір залежить від налаштування «Головна сторінка відображає» — статична сторінка йде в page-гілку, стрічка постів у home.php.

Дочірня тема виграє не тому, що має якийсь пріоритет, а через порядок пошуку всередині locate_template(): спершу STYLESHEETPATH (активна, тобто дочірня, тема), потім TEMPLATEPATH (батьківська), потім wp-includes/theme-compat. Тому перекриття будь-якого шаблону — це просто файл з такою самою назвою в теці дочірньої теми, без жодної реєстрації. Сама дочірня тема — це тека з style.css, у заголовку якого є рядок Template: з іменем теки батьківської теми. Стилі батьківської теми дочірня має підключити сама через wp_enqueue_style на хуку wp_enqueue_scripts — застарілий @import у CSS сповільнює завантаження і його давно не використовують.

Виняток один, але важливий: functions.php через locate_template() не проходить. WordPress підключає обидва файли — спершу дочірній, потім батьківський, — тому копіювати батьківський цілком не можна, це фатальна помилка про повторне оголошення. Замінити функцію батьківської теми вдасться лише тоді, коли вона обгорнута в if (! function_exists()); інакше залишаються remove_action, remove_filter або передбачені темою фільтри. Так само не перекриється частина шаблону, яку батьківська тема підключає жорстким include get_template_directory().'/...' замість get_template_part() — це найчастіша причина «чому мій файл ігнорується».

Коли файлу створювати не хочеться або код живе в плагіні, у вибір можна втрутитися фільтрами: {$type}_template_hierarchy (зʼявився у WP 4.7) міняє список кандидатів до пошуку, {$type}_template — уже знайдений шлях, а template_include спрацьовує останнім і перекриває всіх. Обмеження теж варто памʼятати: у блокових темах (WP 5.9 і новіші) та сама логіка додатково шукає HTML-файли в теці templates/ і шаблони, збережені користувачем у базі як записи wp_template, і знайдений блоковий шаблон має перевагу над однойменним PHP-файлом. І практична порада замість зубріння схеми: повісьте на template_include логер або поставте Query Monitor — він показує і перелік кандидатів, і файл-переможець.

// wp-content/themes/parent-child/style.css має містити заголовок:
// Theme Name: Parent Child
// Template: parent      <- імʼя ТЕКИ батьківської теми, не її назва

// functions.php дочірньої теми: він не перекриває батьківський, а додається до нього
add_action('wp_enqueue_scripts', function (): void {
    // get_template_directory_uri() = батьківська тема, get_stylesheet_* = активна (дочірня)
    wp_enqueue_style('parent-style', get_template_directory_uri().'/style.css');

    wp_enqueue_style(
        'child-style',
        get_stylesheet_uri(),
        ['parent-style'], // вантажимо після батьківського, щоб правила перебивали
        wp_get_theme()->get('Version')
    );
});

// Перекриття файлом: wp-content/themes/parent-child/single-product.php
// Достатньо однакової назви — locate_template() перевіряє дочірню тему першою.

// Частини шаблону підключаємо так, щоб їх теж можна було перекрити з дочірньої теми
get_template_part('parts/product', 'card'); // шукає parts/product-card.php, потім parts/product.php
// а НЕ: include get_template_directory().'/parts/product-card.php'; — це жорстко батьківська тема

// Додати власного кандидата перед стандартними, без правки ядра теми
add_filter('single_template_hierarchy', function (array $templates): array {
    if (has_term('sale', 'product_cat')) {
        array_unshift($templates, 'single-product-sale.php');
    }

    return $templates; // фільтр мусить повернути масив
});

// Діагностика: який саме файл виграв
add_filter('template_include', function (string $template): string {
    error_log('template: '.$template); // спрацьовує останнім, після всіх *_template

    return $template;
}, PHP_INT_MAX);
Що ієрархія — це не магія, а список кандидатів: get_query_template() віддає масив імен від конкретного до загального, а locate_template() бере перший наявний файл.
Що child theme виграє не через «пріоритет теми», а через порядок пошуку в locate_template(): STYLESHEETPATH (дочірня), потім TEMPLATEPATH (батьківська), потім theme-compat.
Що functions.php — виняток: він не перекривається, а завантажується додатково, причому дочірній раніше за батьківський.
Що index.php обовʼязковий і є останнім кандидатом для будь-якого запиту, тому «білий екран» через ієрархію не буває — буває неправильний файл.
Що для front page і блогу правила різні: front-page.php перекриває обидва варіанти, а далі все залежить від налаштування «Головна сторінка відображає» — статична сторінка йде в page-ієрархію, стрічка постів у home.php.
Що перекрити вибір можна й без файлу: фільтрами {$type}_template_hierarchy (з WP 4.7), {$type}_template і template_include, який спрацьовує останнім.
Плутати page-{slug}.php і page-{id}.php з назвою заголовка: слаг береться з post_name, тому сторінка «Контакти» з URL /kontakty/ шукає page-kontakty.php, а не page-contacts.php.
Правити файли батьківської теми напряму й втрачати зміни при оновленні.
Копіювати в дочірню тему functions.php батьківської цілком — отримуєте фатальну помилку «Cannot redeclare function», бо обидва файли виконуються.
Підключати частини шаблону через include get_template_directory().'/parts/card.php' замість get_template_part('parts/card') — жорсткий шлях у батьківську тему вимикає перекриття з дочірньої.
Вважати, що category-5.php спрацює для дочірньої категорії: ієрархія бере слаг і ID саме поточного терміна, без успадкування від батьківського.
Забувати рядок Template: у style.css дочірньої теми або писати туди назву теми замість імені теки батьківської.
ПОРАДА

Скажіть, що будь-яку сторінку можна продіагностувати за пів хвилини: у дочірній тезі повісити на template_include функцію, яка логує обраний файл, або поставити Query Monitor — він показує і список кандидатів, і переможця. Це сильніше за перелік файлів напамʼять.

оновлено 5 вересня 2026 · ліцензія CC-BY-SA-4.0 Знайшли неточність? Напишіть →
ПЕРЕВІРТЕ СЕБЕ

Ієрархія — це впорядкований список імен файлів, а перевага дочірньої теми випливає з порядку пошуку в locate_template(): STYLESHEETPATH, потім TEMPLATEPATH.