Шаблон WooCommerce, который правишь напрямую в папке плагина, слетает при первом же обновлении. Я видел это на нескольких проектах: до меня кто-то отредактировал content-product.php прямо в /wp-content/plugins/woocommerce/templates/, и после апдейта до версии 8.3 карточка товара откатилась к дефолтному виду, а клиент неделю не понимал, куда делись отзывы и кастомные бейджи наличия. Правильный путь - копировать файлы шаблонов в тему, а лучше в дочернюю, и работать с приоритетом поиска, который WooCommerce использует сам.
По теме статьи
Готовое решение
Скрипт расчёта налога (НДС) в корзине Tilda
Автоматический расчёт НДС отдельной строкой в корзине Tilda — для США, ЕС и B2B.
от5 000 ₽
Интернет-магазин
Интернет-магазин под ключ
Интернет-магазин под ключ — на Tilda, WordPress + WooCommerce, Next.js Commerce или кастомный бэкенд. Подберу платформу под бюджет, ассортимент и
от80 000 ₽
Зачем переопределять шаблоны WooCommerce, а не править файлы плагина
Плагин WooCommerce обновляется часто, и разработчики регулярно меняют структуру шаблонов: добавляют хуки, убирают устаревшую разметку, переводят часть интерфейса на блоки Gutenberg. Если правки внесены прямо в файлы плагина, при следующем обновлении WordPress их просто перезапишет без предупреждения и без бэкапа. На практике это выглядит так: сайт месяц работал с кастомной версткой карточки товара, потом клиент нажал «Обновить» в админке, и дизайн за секунду вернулся к дефолту WooCommerce.
Второй риск не такой очевидный, но бьет больнее. Если правки лежат в плагине, их не видно в git-диффе темы, и через полгода никто, включая меня, не вспомнит, что именно меняли и зачем. Переопределение через тему решает обе проблемы: WooCommerce сначала ищет файл в теме и только потом в своей папке, поэтому обновление плагина трогает только его собственные файлы, а копия в теме остается нетронутой.
Как WooCommerce ищет файлы шаблонов в теме
Логика поиска зашита в функции wc_locate_template() и построена на трех уровнях приоритета:
yourtheme/woocommerce/имя-шаблона.php- переопределение в активной теме, высший приоритет;yourtheme/имя-шаблона.php- старый вариант без подпапки, WooCommerce поддерживает его для обратной совместимости, но я так не делаю - слишком легко перепутать шаблон темы с шаблоном магазина;wp-content/plugins/woocommerce/templates/имя-шаблона.php- дефолтный файл плагина, подключается, если в теме ничего не найдено.
Структура папки в теме зеркалит структуру плагина один в один, вплоть до вложенных каталогов:
themename/
woocommerce/
content-product.php
single-product/
price.php
add-to-cart/
simple.php
checkout/
thankyou.php
Практика: копирую шаблон карточки товара в дочернюю тему
Беру для примера content-product.php - шаблон карточки товара в архиве магазина. Порядок действий у меня почти всегда один и тот же:
- Создаю дочернюю тему, если её еще нет - переопределения в родительской теме слетят при обновлении темы точно так же, как правки в плагине;
- Копирую файл из
wp-content/plugins/woocommerce/templates/content-product.phpвwp-content/themes/моя-дочерняя-тема/woocommerce/content-product.php, сохраняя относительный путь; - Смотрю на комментарий в шапке файла - там указана версия шаблона, например
@version 8.6.0. Эту версию фиксирую у себя в заметке, чтобы после апдейта WooCommerce было с чем сверить; - Вношу правки и проверяю карточку сразу в каталоге, в результатах поиска и в блоке «Похожие товары» - один и тот же шаблон нередко подключается в нескольких местах магазина.
Дочернюю тему подключаю штатно, без плагинов-прослоек:
<?php
add_action( 'wp_enqueue_scripts', 'kalinkindev_child_theme_styles' );
function kalinkindev_child_theme_styles() {
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/style.css', array( 'parent-style' ) );
}
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Хуки WooCommerce vs полное переопределение файла
Перед тем как копировать файл в тему, смотрю, нельзя ли обойтись хуком - большинство шаблонов WooCommerce вызывают do_action() в нескольких точках, и туда можно добавить свою функцию без единой строки готовой верстки:
<?php
add_action( 'woocommerce_before_shop_loop_item_title', 'kalinkindev_add_stock_badge', 15 );
function kalinkindev_add_stock_badge() {
global $product;
if ( $product->is_in_stock() ) {
echo '<span class="stock-badge">В наличии</span>';
}
}
| Способ | Что меняешь | Риск при обновлении | Когда применяю |
|---|---|---|---|
| Хуки (add_action/remove_action) | добавление, скрытие или перестановку блоков без изменения верстки | низкий, сигнатура хука переживает большинство релизов | бейдж наличия, доп. поле, изменение порядка блоков на карточке |
| Полный override шаблона | саму HTML-структуру файла | выше - при мажорном апдейте нужно вручную сверять с новым дефолтным файлом | меняю разметку целиком, встраиваю сторонний виджет в структуру страницы |
| Override + хуки внутри своего файла | точечные вставки внутри скопированного файла | средний, зависит от объема правок | стандартный случай для большинства задач клиентов |
На практике почти всегда выигрывает третий вариант: беру дефолтный файл почти без изменений и добавляю в него хуки вместо того, чтобы переписывать разметку целиком. Тогда при обновлении WooCommerce достаточно сравнить свой файл с новым дефолтным через diff и перенести две-три строки, а не разбираться, что изменилось во всем шаблоне.
Что ломается при обновлении WooCommerce и как это отследить
Самое неприятное обновление за последние пару лет для меня - переход WooCommerce на блочный чекаут (Cart and Checkout blocks), который стал вариантом по умолчанию начиная с версии 8.3. У меня был проект с интеграцией эквайринга Т‑Банка, где я переопределял checkout/form-checkout.php, чтобы добавить свои поля и вывод виджета оплаты. После обновления страница оформления заказа у части покупателей стала открываться в блочном режиме, где старый файл шаблона вообще не подключается - подключение полей ушло в другой механизм, через Store API и React-компоненты. Пришлось явно оставить магазин на классическом чекауте в настройках WooCommerce и параллельно переписывать интеграцию под блочный API, чтобы не откладывать переход на потом.
Похожая история была с зоной доставки СДЭК: кастомный вывод стоимости и сроков в cart/cart-shipping-method.php перестал получать нужные данные после того, как WooCommerce изменил формат объекта rate в одном из минорных релизов. Помогло то, что этот шаблон я не переопределял целиком, а вставлял свой код через хук woocommerce_cart_shipping_method_full_label - его сигнатура не менялась несколько лет.
Состояние переопределений отслеживаю через раздел WooCommerce Status: там показан список файлов, у которых версия в шапке отличается от версии в актуальном плагине, и они подсвечены желтым. Это первое, что проверяю после любого обновления WooCommerce на боевом сайте, до того как об этом напишет клиент. Если правок много и магазин рассчитывает работать без сюрпризов после каждого релиза плагина, такие вещи разумнее не проверять от случая к случаю, а отдать на постоянное сопровождение интернет-магазина на WooCommerce, куда входит в том числе проверка шаблонов после обновлений.
Частые ошибки при кастомизации шаблонов WooCommerce
- Правки прямо в /wp-content/plugins/woocommerce/ - обнуляются при любом обновлении плагина, без вариантов;
- Переопределение в родительской теме вместо дочерней - слетает при обновлении темы тем же способом;
- Копирование всего файла ради одной строки правки - потом невозможно быстро понять, что изменил именно я, а что было в оригинале;
- Игнорирование раздела WooCommerce Status - «устаревшие шаблоны» там не декоративная надпись, а конкретный список файлов, которые разошлись с логикой плагина;
- Проверка магазина только в классическом чекауте, хотя часть установок WooCommerce уже работает с блочным чекаутом по умолчанию;
- Хардкод обращений к файлам темы внутри плагинов интеграций - эквайринга, СДЭК, доставки - при смене темы такие правки теряются, разумнее выносить их в отдельный must-use плагин.
Частые вопросы
Как понять, что мой шаблон устарел после обновления WooCommerce?
Открываю WooCommerce, раздел Статус, вкладку Шаблоны. Там список файлов с пометкой об устаревании и указанием версии ядра рядом с версией моего переопределения - если они разошлись, сверяю свой файл с актуальным через diff.
Можно ли переопределить только часть шаблона, а не весь файл?
Да, и это предпочтительный способ в большинстве случаев. Шаблоны WooCommerce вызывают хуки вроде woocommerce_before_shop_loop_item или woocommerce_single_product_summary с привязанными к ним функциями через add_action и remove_action - через них закрывается почти все, что обычно нужно клиентам, без копирования файла целиком.
У меня уже не дочерняя тема, а прямые правки в родительской - что делать перед следующим обновлением темы?
Перед обновлением создаю дочернюю тему, переношу в нее папку woocommerce/ со всеми переопределениями и функции из functions.php, которые относятся к магазину. Только после этого обновляю родительскую тему, иначе правки исчезнут при первом же апдейте.
Ломает ли блочный чекаут старые переопределения шаблонов?
Частично да. Файлы checkout/form-checkout.php и cart/cart.php в блочном режиме не используются - вместо них работают React-компоненты и Store API. Если у магазина есть кастомизация чекаута, перед обновлением WooCommerce до версии с блоками по умолчанию стоит либо явно оставить классический чекаут в настройках, либо переносить логику в хуки блочного API.