Как мне получить слаг текущей страницы?

100

Я пытаюсь получить кусок текущей страницы WordPress вне цикла. Заголовок страницы возвращается с wp_title (), но как я могу получить слаг?

<li>
  <a href="/slug-of-current-page/">
    <?php wp_title('', true); ?>
  </a>
</li>
Сарыташ
источник

Ответы:

152

Используйте глобальную переменную $post:

<?php 
    global $post;
    $post_slug = $post->post_name;
?>
Арвинд Пал
источник
3
Спасибо. Ваше решение отлично работает. Просто нужно повторить слизняк:<?php global $post; $post_slug=$post->post_name; echo $post_slug; ?>
Сарыташ
1
Как сказал Сарыташ, тебе это нужно echo. Итак, это было бы идеально:<?php global $post; echo $post->post_name; ?>
its_me
Как насчет $WP_Post?
Питер Мортенсен
68

Согласно другим ответам, слизняк хранится в post_nameсобственности. Хотя к нему можно получить прямой доступ, я предпочитаю (недоиспользуемую) get_post_field()функцию для доступа к свойствам записей, у которых нет подходящего API для них.

Это требует, чтобы сообщение было предоставлено явно и не по умолчанию для текущего, поэтому в полном объеме для текущего сообщения это будет:

$slug = get_post_field( 'post_name', get_post() );
Rarst
источник
12
Стоит отметить, что если вы находитесь в цикле, вы можете использовать get_post_fieldбез второго аргумента ( документы )
jmarceli
26

РЕДАКТИРОВАТЬ 5 АПРЕЛЯ 2016

После поисков для большей надежности, я закончил тем, что сделал этот ответ к следующему сообщению, которое приводит к этому редактированию: ( Не забудьте проверить это )

Самый надежный метод до настоящего времени, который я мог придумать, заключается в следующем:

// Get the queried object and sanitize it
$current_page = sanitize_post( $GLOBALS['wp_the_query']->get_queried_object() );
// Get the page slug
$slug = $current_page->post_name;

Таким образом, вы на 99,9999% уверены, что каждый раз получаете правильные данные.

ОРИГИНАЛЬНЫЙ ОТВЕТ

Другой более безопасной альтернативой этой проблеме является использование get_queried_object()текущего объекта запроса для получения фрагмента страницы, который удерживается post_nameсвойством. Это может быть использовано в любом месте вашего шаблона.

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

Использование get_queried_object()для получения объекта текущей страницы гораздо надежнее и с меньшей вероятностью будет изменено, если только вы не используете зло, query_postsкоторое разрушает основной объект запроса, но тогда все зависит только от вас.

Вы можете использовать выше, как следует

if ( is_page() )
    $slug = get_queried_object()->post_name;
Питер Гусен
источник
Я должен сказать, что query_postsэто не зло, если вы хотите изменить основной запрос , что, как вы обычно не делаете и часто злоупотребляете :)
jave.web
11

Самый простой способ получить слаг:

<?php echo basename(get_permalink()); ?>
Tracey
источник
2
это зависит от настроек постоянной ссылки. Если вы используете «простую» настройку, ссылки будут выглядеть http://domain/?p=123, оставляя вас с ?p=123.
Мене
8

Учитывая пример кода, похоже, что вам действительно нужна ссылка. В этом случае вы можете использовать get_permalink () , который можно использовать вне цикла. Это должно делать то, что вам нужно более надежно, чем использование пост-слаг.

Мэтью Бойнс
источник
4
Это полный URL, а не только слизень.
Фред
2

Возможно, это старый вопрос, но я создал функции get_the_slug () и the_slug () на основе ваших ответов.

if ( !function_exists("get_the_slug") ) {
    /**
    * Returns the page or post slug.
    *
    * @param int|WP_Post|null $id (Optional) Post ID or post object. Defaults to global $post.
    * @return string
    */
    function get_the_slug( $id = null ){
        $post = get_post($id);
        if( !empty($post) ) return $post->post_name;
        return ''; // No global $post var or matching ID available.
    }
    /**
    * Display the page or post slug
    *
    * Uses get_the_slug() and applies 'the_slug' filter.
    *
    * @param int|WP_Post|null $id (Optional) Post ID or post object. Defaults to global $post.
    */
    function the_slug( $id=null ){
        echo apply_filters( 'the_slug', get_the_slug($id) );
    }
}
Earlee
источник
0

Чуть дальше ответ @Matthew Boynes, если вы заинтересованы в получении родительского слага (если есть), то я нашел эту функцию полезной:

function mytheme_get_slugs() {
    if ( $link = get_permalink() ) {
        $link = str_replace( home_url( '/' ), '', $link );
        if ( ( $len = strlen( $link ) ) > 0 && $link[$len - 1] == '/' ) {
            $link = substr( $link, 0, -1 );
        }
        return explode( '/', $link );
    }
    return false;
}

Например, чтобы добавить слаг (ы) к классу тела:

function mytheme_body_class( $classes ) {
    if ( $slugs = mytheme_get_slugs() ) {
        $classes = array_merge( $classes, $slugs );
    }
    return $classes;
}
add_filter( 'body_class', 'mytheme_body_class' );
Бонгер
источник
0

Если вам нужен более скрытый ответ, вы можете использовать следующий SQL-запрос для извлечения всех сообщений, которые являются либо сообщениями, либо страницами, либо пользовательскими таксономиями в любое время, даже если на данный момент еще не было обработано никаких перехватчиков.

Сырой SQL:


SELECT `id`, `post_type` AS `type`, `post_author` AS `author`, `post_name` AS 
`slug`, `post_status` AS `status`
FROM wp_posts 
WHERE `post_type` NOT IN ('attachment', 'nav_menu_item', 'revision')
AND `post_status` NOT IN ('draft', 'trash')
ORDER BY `id`;

Это работает даже в самой первой строке вашего файла функций, даже перед хуками mu_plugins_loadedили init.

@нота

Это предполагает, что у вас есть стандартный префикс базы данных wp_posts. Если вам нужно учитывать префиксы переменных, вы можете довольно легко получить правильную таблицу записей через PHP, выполнив следующие действия:

<?php
global $wpdb;
$table = $wpdb->posts;
$query = "SELECT `id`, `post_type` AS `type`, `post_author` AS `author`, `post_name` AS 
`slug`, `post_status` AS `status`
FROM " . $table . "
WHERE `post_type` NOT IN ('attachment', 'nav_menu_item', 'revision')
AND `post_status` NOT IN ('draft', 'trash')
ORDER BY `id`;"

Затем запустите либо $wpdb, mysqliили , PDOнапример. Поскольку в этом запросе нет пользовательского ввода, его можно безопасно выполнять без подготовленного оператора, если в него не введены никакие переменные.

Я бы предложил сохранить это как частное статическое значение класса, чтобы к нему можно было обращаться без необходимости повторного запуска запроса более одного раза на страницу для лучшей производительности, что-то вроде этого:

class Post_Cache
{
    private static $post_cache;

    public function __construct()
    {
        //This way it skips the operation if it's already set.
        $this->initCache();
    }

    public function get($id, $type = null)
    {
        if ( !(is_int( $id ) && array_key_exists( $id, self::$post_cache ) ) )
            return false;
        }
        if ( !is_null( $type ) )
        {
            //returns the specific column value for the id
            return self::$post_cache[$id][$type];
        }
        //returns the whole row
        return self::$post_cache[$id];
    }

    private function initCache()
    {
        if ( is_null(self::$post_cache) )
        {

            $query = "...";
            $result = some_query_method($query); //Do your query logic here.
            self::$post_cache = $result;
        {
    }
}

использование

$cache = new \Post_Cache();

//Get the page slug
$slug = $cache->get( get_the_ID(), 'slug');

if ($cache->get( get_the_ID() ))
{
    //post exists
} else {
    //nope, 404 'em
}
if ( $cache->get( get_the_ID(), 'status') === 'publish' )
{
    //it's public
} else {
    //either check current_user_can('whatever_permission') or just 404 it,
    //depending whether you want it visible to the current user or not.
}
if ( $cache->get( get_the_ID(), 'type') === 'post' )
{
    //It's a post
}
if ( $cache->get( get_the_ID(), 'type') === 'page' )
{
    //It's a page
}

Вы получаете суть. Если вам нужна дополнительная информация, вы можете получить их в соответствии с нормой сnew \WP_Post( get_the_ID() );


Это позволит вам проверить сообщения в любое время, даже если цикл wordpress не достиг точки, в которой он находит ваш запрос приемлемым. Это немного более оптимизированная версия того же запроса, выполняемого самим ядром Wordpress. Этот отфильтровывает все ненужные вещи, которые вы не хотели бы возвращать, и просто дает вам хорошо организованный список с соответствующим идентификатором автора, типом сообщения, слагом и видимостью. Если вам нужны дополнительные сведения, вы можете получить их в обычном режиме new \WP_Post($id);или использовать любые другие встроенные функции Wordpress с любой из соответствующих строк таблицы, даже вне цикла.

Я использую аналогичную настройку в паре моих собственных тем и плагинов, и она работает довольно хорошо. Он также безопасен и не оставляет внутренних данных плавающими в глобальной области, где он может быть переопределен, как большинство вещей в Wordpress.

mopsyd
источник
0

Я, честно говоря, не понимаю, почему ни один из ответов просто не делает:

global $wp;
$current_slug = $wp->request;

// Given the URL of https://example.com/foo-bar
if ($current_slug === 'foo-bar') {
  // the condition will match.
}

Это работает для всех сообщений, страниц, пользовательских маршрутов.

leymannx
источник
-1

Динамический вызов страницы в WordPress.

<?php
    get_template_part('foldername/'.basename(get_permalink()),'name');
    ?>
Sujoy Bhowmick
источник