Можно ли получить ссылку на страницу из её слага?
Возможно ли получить постоянную ссылку страницы, используя только слаг? Я знаю, что можно получить ссылку на страницу по ID, используя get_page_link()
:
<a href="<?php echo get_page_link(40); ?>">Карта</a>
Мне интересно, есть ли способ сделать то же самое со слагом страницы - например, так:
<a href="<?php echo get_page_link('map'); ?>">Карта</a>

Это то, что вы ищете:
get_permalink( get_page_by_path( 'map' ) )
get_permalink( get_page_by_title( 'Карта' ) )
home_url( '/map/' )
Ссылки на документацию:

get_page_by_path()
возвращает массив со всей информацией о странице. get_permalink()
принимает ID страницы в качестве первого аргумента. Я подумал, что нужно явно передать значение ID.

@Jonathan: Это не всегда задокументировано, но многие функции WP принимают в качестве аргумента как числовые ID, так и полные объекты записей.

Похоже, что get_page_by_path() может быть довольно сложной в использовании при работе с дочерними страницами...

Я использую 1 для своих дочерних страниц без проблем. Действительно не вижу в этом сложности.

неверный ответ, минусуйте в нирвану пожалуйста. Путь не совпадает со слагом. Пример: страница имеет родительскую страницу с названием abc
, сама страница имеет слаг 123
. Теперь путь выглядит как abc/123
, а слаг - 123
. Пожалуйста, удалите этот неправильный ответ. get_page_by_path( '123' )
не сработает.

В моем случае пришлось использовать первый вариант, и он сработал, потому что второй (get_page_by_title) возвращал ссылку на другую запись (не страницу) с похожим (но не идентичным) slug. Не знаю, почему так происходило.

Думаю, это можно улучшить:
function get_page_by_slug($page_slug, $output = OBJECT, $post_type = 'page' ) {
global $wpdb;
$page = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type= %s", $page_slug, $post_type ) );
if ( $page )
return get_page($page, $output);
return null;
}
следуя шаблону "оригинальной" функции get_page_by_title
в WordPress. (строка 3173)
С уважением

Почему? Это не создает полный объект записи просто для получения ID.

Последний комментарий - я думаю, что в этом SQL запросе нужно добавить еще одно условие: function get_page_by_slug($page_slug, $output = OBJECT, $post_type = 'page' ) { global $wpdb; $page = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type= %s AND post_status = 'publish'", $page_slug, $post_type ) ); if ( $page ) return get_page($page, $output); return null; }

@webcitron Думаю, это просто следует оригинальному шаблону Wordpress получения поста по 'title', только заменяет на 'slug'. (проверьте ссылку)

Это хороший ответ. Это обходит возможность того, что какой-то плагин может маскировать вашу страницу или неправильно её фильтровать. Если вы вернёте id из таблицы постов, то сможете создать экземпляр \WP_Post
из него, и это будет напрямую работать во всех функциях Wordpress, которые проверяют другие значения. \WP_Post
также предоставляет методы для непосредственного поиска большинства связанных данных о посте.

Это метод, опубликованный Томом МакФарлином в своем блоге:
/**
* Возвращает постоянную ссылку для страницы на основе переданного ярлыка (slug).
*
* @param string $slug Ярлык страницы, на которую нужно создать ссылку.
* @param string $post_type Тип записи (необязательный параметр).
* @return string Постоянная ссылка страницы
* @since 1.0
*/
function wpse_4999_get_permalink_by_slug( $slug, $post_type = '' ) {
// Инициализация переменной для хранения ссылки
$permalink = null;
// Формируем аргументы для WP_Query
$args = array(
'name' => $slug,
'max_num_posts' => 1
);
// Если передан необязательный параметр, добавляем его в массив аргументов
if( '' != $post_type ) {
$args = array_merge( $args, array( 'post_type' => $post_type ) );
}
// Выполняем запрос (и сбрасываем его)
$query = new WP_Query( $args );
if( $query->have_posts() ) {
$query->the_post();
$permalink = get_permalink( get_the_ID() );
wp_reset_postdata();
}
return $permalink;
}
Метод работает как с пользовательскими типами записей, так и со встроенными (такими как post
и page
).

принятый ответ неверен, потому что иерархические страницы работают не так. Проще говоря, ярлык (slug) не всегда соответствует пути страницы или записи. Например, если ваша страница имеет дочернюю, путь будет родительский-ярлык/дочерний-ярлык
, и функция get_page_by_path
не сможет найти дочерний-ярлык
таким образом. Правильное решение выглядит так:
function mycoolprefix_post_by_slug($the_slug, $post_type = "page"){
$args = array(
'name' => $the_slug,
'post_type' => $post_type,
'post_status' => 'publish',
'numberposts' => 1
);
$my_page = get_posts($args)[0];
return $my_page;
}
<a href="<?php echo mycoolprefix_post_by_slug('map'); ?>">Карта</a>

Попробуйте так:
<a href="<?php echo get_page_link( get_page_by_path( 'map' ) ); ?>">Карта</a>
Функция get_page_by_path( 'path' )
возвращает объект страницы/записи, который затем можно использовать в get_page_link()
, так как она принимает объект страницы/записи и возвращает постоянную ссылку.

function theme_get_permalink_by_title( $title ) {
// Инициализируем значение постоянной ссылки
$permalink = null;
// Пытаемся получить страницу по переданному заголовку
$page = get_page_by_title( strtolower( $title ) );
// Если страница существует, получаем её постоянную ссылку
if( null != $page ) {
$permalink = get_permalink( $page->ID );
} // end if
return $permalink;
} // end theme_get_permalink_by_title
Используйте эту функцию следующим образом
if( null == theme_get_permalink_by_title( 'Регистрация на сайте' ) ) {
// Постоянная ссылка не существует, обработайте это как считаете нужным
} else {
// Страница существует, выполните необходимые действия
} // end if/else
