Принудительный показ страниц вместо категорий в WordPress
Я пытаюсь создать SILO-структуру на одном из моих сайтов WordPress.
Я всегда использовал опцию в плагине Yoast SEO "Убрать базовый префикс категории (обычно /category/) из URL категории".
Поэтому мои страницы категорий имеют такой URL: sitename.com/apple/ (где "apple" - это страница категории)
Теперь я хочу создать новую "страницу" с таким же слагом apple.
Я могу легко создать новую страницу "apple", однако, когда я перехожу по адресу sitename.com/apple/, отображается страница категории -- вместо новой созданной страницы.
Мой вопрос: Существует ли способ "переопределить" стандартный приоритет категории над страницей? Я хотел бы показывать страницу, потому что тогда у меня будет контроль над ней -- я смогу настраивать, добавлять больше контента и легко изменять их (кроме того, страницы помогут мне лучше структурировать мой сайт)
Ценю вашу помощь!

Одно из возможных решений — не изменять базовый префикс категорий и оставить его как есть, но вместо этого модифицировать вывод ссылок на категории, удаляя базовый префикс с помощью фильтра. Конечно, это приведёт к ошибке 404, если вы не создали страницы, на которые ведут эти ссылки, поэтому необходимо создать страницу для каждой категории.
function wpa_alter_cat_links( $termlink, $term, $taxonomy ){
if( 'category' != $taxonomy ) return $termlink;
return str_replace( '/category', '', $termlink );
}
add_filter( 'term_link', 'wpa_alter_cat_links', 10, 3 );
Рекомендуется тщательно протестировать это решение на предмет побочных эффектов. Используйте на свой страх и риск!
РЕДАКТИРОВАНИЕ — изменение только ссылок на родительские категории:
function wpa_alter_cat_links( $termlink, $term, $taxonomy ){
if( 'category' == $taxonomy && 0 == $term->parent ){
return str_replace( '/category', '', $termlink );
}
return $termlink;
}
add_filter( 'term_link', 'wpa_alter_cat_links', 10, 3 );

Мило, это именно то, что я хотел! Не могу поверить, что это было так просто и возможно. Огромное спасибо!
Но есть проблема. Страницы подкатегорий ведут на 404. Можно ли это исправить?
Дополнительные детали: Для моих сайтов необходимы хлебные крошки. Вот формат: Главная -> Кат. 1 -> Подкат. 2 -> запись. Кат. 1 теперь это СТРАНИЦА, но подкат. 2 ведет на 404.

вам нужно создать дочерние страницы под родительскими страницами для подкатегорий.

Ты гений, вот кто ты. Большое спасибо. Это действительно требует много времени и усилий. Думаю, я все равно это сделаю. Но все же хотел бы узнать, могу ли я назначить только родительскую категорию как СТРАНИЦУ, а подкатегории оставить стандартными страницами категорий?

в приведенной выше функции проверьте, равно ли $term->parent
нулю. Дочерние категории будут иметь ID категории в $term->parent
, а у категорий верхнего уровня это значение будет просто нулевым.

Я понимаю, что нужно использовать if ($term->parent == 0), но не уверен, куда вставить этот код. Потратил некоторое время на поиски в Google, но не смог разобраться, как это сделать. Буду очень признателен, если вы исправите код. :)

Я создал следующую, довольно простую функцию, чтобы при загрузке контента страницы имели более высокий приоритет, чем категории.
(Примечание: возможно, это не самый лучший, но простой способ. Я обнаружил проблему при использовании плагина Advanced Custom Fields — по умолчанию он не вставляет пользовательские поля ни старой, ни новой страницы. Добавление get_queried_object()->ID
в качестве второго параметра для функции get_field()
в ACF решило эту проблему. Тщательно протестируйте это в вашей среде WordPress.)
function loadPageFirst() {
// получаем текущую категорию
$actualCategory = get_category( get_query_var('cat') );
// получаем страницу с таким же слагом
$matchingPage = get_page_by_path( $actualCategory->slug );
// Если совпадений нет, загружаем стандартный шаблон архива и завершаем выполнение (измените, если используете кастомный шаблон, например category.php)
if (!$matchingPage) {
include( get_template_directory() . '/archive.php');
die();
}
// Создаем новый запрос с ID страницы и загружаем шаблон страницы
query_posts( 'page_id=' . $matchingPage->ID );
include( get_template_directory() . '/page.php');
die();
}
add_filter( 'category_template', 'loadPageFirst' );
Вы можете добавить этот код в functions.php вашей темы. Похоже, он корректно работает с плагином Yoast SEO.

Я считаю, что вам не нужно включать archive.php и die() — в зависимости от вашей темы это может не сработать. Можно просто использовать return. (Но огромное спасибо за код!)

Вот очень простое и полностью рабочее решение: https://stackoverflow.com/questions/32310453/make-wordpress-use-the-page-instead-of-category
Для полноты картины:
Исходные данные
- example.com — домен
- У меня есть страница WordPress под названием "foobar" с контентом
- У меня есть категория записей WordPress под названием "foobar"
- У меня есть запись WordPress с заголовком "fun things to do with foobars", и для неё установлена категория "foobar"
Ожидания
- Когда я перехожу на example.com/foobar, я хочу видеть страницу о foobars, а не страницу категории WordPress, которая показывает все записи блога с этой категорией.
- Когда я перехожу к записи о "fun things", URL должен быть example.com/foobar/fun-things-to-do-with-foobars/
Настройка
Вот моя настройка (она не требует дополнительных плагинов или правки кода). У меня установлены плагины WP Rocket и Yoast, на которых я сосредоточусь в этой теме.
WP Dashboard → Настройки → Постоянные ссылки
Выберите "Произвольная структура" и введите /%category%/%postname%/ в поле
На той же странице измените "Префикс категорий" на одну точку "." (без кавычек, просто точка)
У меня установлен Yoast, который я настроил на переопределение настроек постоянных ссылок, но я считаю, что это помешало моей задаче.
WP Dashboard → SEO → Дополнительно → Постоянные ссылки (вкладка)
"Изменение URL → Удалить префикс категорий..." = Оставить
Затем нужно очистить кеш. Я использую WP Rocket для кеширования, поэтому я очистил кеш, и теперь всё работает так, как должно.
Примечание: не забудьте сохранить изменения после шагов 3 и 5

Зависит от ситуации. Если вы пытаетесь сделать две разные страницы с одинаковым URL — это плохая идея. Но если вас не волнуют страницы категорий, вы можете перенаправлять их на свои страницы.
RedirectMatch 301 ^/category/(.*)$ /$1
Этот код нужно добавить в файл .htaccess
, и он будет перенаправлять /category/страница на /страница/

Спасибо! Однако, как я уже упоминал, у меня нет базовой категории, прикрепленной к URL. И я не могу использовать традиционный 301 редирект, так как оба URL одинаковые.

"WordPress-подход" к решению этой задачи заключается в создании пользовательского PHP-шаблона для страницы категории и применении ваших настроек там, а не через создание уникальной "Страницы".
Также доступно множество плагинов, которые позволяют добавлять изображения и другие пользовательские поля на страницу архива категорий, что может быть лучшим вариантом, если вы предпочитаете не изменять файлы темы.
В качестве альтернативы, я бы предложил добавить базовый URL для категории, который может содержать одно из ваших основных ключевых слов.

Проблема, на мой взгляд, в том, что WordPress обрабатывает "страницы" иначе. Они ранжируются лучше, чем традиционные страницы категорий. Многие SEO-специалисты делают то, о чем я спросил выше — полностью удаляют категорию и заменяют её страницами.

Вероятно, стоит подробнее объяснить, как добавить этот шаблон страницы (подсказка: иерархия шаблонов) и т.д.

@Sid - если контент идентичен, почему архив категории должен ранжироваться иначе, чем страница?

@Milo - Содержание не будет идентичным, только URL. На страницах будет гораздо более структурированный контент и ссылки на связанные материалы.

@Sid, я хотел сказать, что аналогичных результатов можно добиться через шаблон категории, подтягивая дополнительный контент из других источников. Быстрый способ реализовать это — плагин Advanced Custom Fields, который позволяет добавлять дополнительный контент на страницы администрирования терминов таксономий — WYSIWYG-редакторы, поля связей и т.д.

Извините, но у меня недостаточно репутации, чтобы комментировать ответ @bencergazda.
Я считаю это лучшим решением. Но у меня возникла ошибка с отображением изображения в шапке темы, так как не получался правильный ID записи.
Для решения я добавил строку в код: "global $post; $post->ID = $matchingPage->ID;"
Результат:
function loadPageFirst() {
// получаем текущую категорию
$actualCategory = get_category( get_query_var('cat') );
// получаем страницу с таким же ярлыком
$matchingPage = get_page_by_path( $actualCategory->slug );
// Если совпадений нет, загружаем стандартный шаблон архива и выходим (измените, если используете кастомный шаблон, например category.php)
if (!$matchingPage) {
include( get_template_directory() . '/archive.php');
die();
}
// Создаем новый запрос с ID страницы и загружаем шаблон страницы
global $post; $post->ID = $matchingPage->ID;
query_posts( 'page_id=' . $matchingPage->ID );
include( get_template_directory() . '/page.php');
die();
}
add_filter( 'category_template', 'loadPageFirst' );
С наилучшими пожеланиями

Извините, но у меня также недостаточно репутации, чтобы комментировать ответ @bencergazda.
Я внес некоторые изменения в его функцию. Убрал часть, которая загружала страницу категории (не требуется), и добавил иерархию страниц:
function loadPageFirst( $file ) {
// получаем текущую категорию
$actualCategory = get_category( get_query_var('cat') );
// получаем страницу с таким же ярлыком (slug)
$matchingPage = get_page_by_path( $actualCategory->slug );
if ( ! $matchingPage ) {
return $file;
}
// Создаем новый запрос с ID страницы и загружаем шаблон страницы
query_posts( 'page_id=' . $matchingPage->ID );
$page_template = get_page_template_slug( $matchingPage->ID ) ? get_page_template_slug( $matchingPage->ID ) : null;
$pages = array(
$page_template,
'page-' . $actualCategory->slug . '.php',
'page-' . $matchingPage->ID . '.php',
'page.php',
'singular.php',
'index.php',
);
foreach ( $pages as $page ) {
$file = get_theme_file_path( $page );
if ( $page === null || ! file_exists( $file ) ) {
continue;
}
return $file;
}
}
add_filter( 'category_template', 'loadPageFirst' );

Это потрясающе. Прошло ровно 10 лет с момента публикации, а решение до сих пор работает идеально. Интересно, возможно ли аналогичное решение для меток? Я хотел бы заменить архивные страницы меток на реальные страницы, которые дают мне больше контроля.
Может кто-нибудь помочь мне в этом? Заранее спасибо!

Пожалуйста, не добавляйте "спасибо" в качестве ответа. Когда у вас будет достаточно репутации, вы сможете голосовать за вопросы и ответы, которые вам помогли. - Из обзора
