Получить ярлык (slug) произвольного типа записи для страницы архива

7 окт. 2012 г., 14:33:27
Просмотры: 64.3K
Голосов: 18

Как мне определить ярлык (slug) произвольного типа записи, когда я нахожусь на странице архива?

Например, если /products/ вызывает шаблон archive-products.php, как (программно) получить ярлык типа записи?

Спасибо

0
Все ответы на вопрос 7
5
24

Чтобы получить текущий тип записи, используйте get_post_type(). Затем запросите get_post_type_object() для всех необходимых данных, например, для получения ярлыка (slug):

$post_type = get_post_type();
if ( $post_type )
{
    $post_type_data = get_post_type_object( $post_type );
    $post_type_slug = $post_type_data->rewrite['slug'];
    echo $post_type_slug;
}
7 окт. 2012 г. 16:48:23
Комментарии

Думаю (не проверял), что get_queried_object() получит ту же информацию за меньшее количество действий.

Rarst Rarst
9 окт. 2012 г. 04:15:53

@Rarst Возможно, но мне кажется, что предложенный мной код проще для понимания.

fuxia fuxia
9 окт. 2012 г. 04:18:13

Решение Toscho неверно, потому что get_post_type возвращает тип записи текущей страницы, и, когда вы находитесь на странице архива, эта функция всегда возвращает "page". Я ищу решение для той же проблемы: когда я нахожусь на странице архива 'books' (например), я хочу получить: 'books'. Когда найду решение - опубликую.

eMarine eMarine
25 июн. 2013 г. 12:58:43

к сожалению, это не так просто, хотя вам будет лучше использовать просто $posttype = get_query_var('post_type'); ... я добавил более комплексную альтернативу.

majick majick
6 июн. 2016 г. 21:56:23

я не думаю, что этот ответ раскрывает всю картину. вам следует проверить правила перезаписи (rewrite rules), так как многие фильтры (например, страница магазина woocommerce) вносят изменения. используйте собственный механизм WordPress, см. мой ответ где-то ниже.

Jonas Lundman Jonas Lundman
21 окт. 2017 г. 20:17:02
4

Я использую этот код вне цикла в шаблоне archive.php, чтобы определить, в каком архиве пользовательских записей я нахожусь.

Это комбинация методов, которые рекомендовали и @toscho, и @Rarst:

$post_type = get_queried_object();
echo $post_type->rewrite['slug'];

Обновление: @majick указал, что это работает только если вы установили rewrite slug для вашего CPT. Rewrite slug является необязательным параметром при регистрации CPT и по умолчанию использует post_type, если не задан.

29 окт. 2014 г. 17:42:33
Комментарии

когда я попробовал это, я получил Notice: Undefined property: stdClass::$rewrite in ***\wp-content\themes\marks-remarks\archive.php on line 4

patrickzdb patrickzdb
20 окт. 2015 г. 16:37:15

это будет работать только если rewrite slug установлен для зарегистрированного CPT, так как он является необязательным и по умолчанию использует post_type

majick majick
3 июн. 2016 г. 06:23:37

Спасибо, что заметили это @majick! Я обновил пост с учётом вашей информации.

Jerry Jerry
3 июн. 2016 г. 17:23:55

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

majick majick
6 июн. 2016 г. 21:53:49
2

Ответы становятся запутанными. И, возможно, я тоже, но главный вопрос:

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

Если вы имеете в виду лендинг-страницу архива типа записи, и когда is_post_type_archive() возвращает true, вам нужен слаг, соответствующий текущему просматриваемому архиву:

/* возвращает /products/ */

$responding_name = str_replace(get_home_url(), '', get_post_type_archive_link(get_query_var('post_type')));

/* продолжаем получать 'products' без слэшей */
$responding_name = str_replace('/', '', $responding_name);

-- КОНЕЦ ОТВЕТА НА ВОПРОС --

Объяснение:

Вы не можете полагаться на зарегистрированный слаг. WordPress тоже не может. Например, при вызове get_post_type_archive_link() WordPress проверяет текущие правила перезаписи для вашей установки.

Где бы вы ни находились — внутри или вне цикла, в текущем архиве или отдельной записи, обратите механизм get_post_type_archive_link(). (ЧПУ включены.)

Рекомендации:

Как упоминалось здесь, тип(ы) записей в текущем запросе могут быть массивом. Вы можете пойти дальше в своих намерениях, отфильтровав нужный тип записи, например:

$post_type = get_query_var('post_type'); 
if(is_array($post_type)) $post_type = reset($post_type);

или

if(isset($post_types[0])) $post_type = $post_types[0];

Другой взгляд:

Пример WooCommerce: зарегистрирован с типом записи 'products', но на самом деле использует переписанное имя правила (shop):

/* возвращает shop */
$responding_name = str_replace('/', '', str_replace(get_home_url(), '', get_post_type_archive_link('product')));

Марк, я использую $responding_name, потому что цели могут различаться. Архива записей не существует, это просто URL.

21 окт. 2017 г. 21:32:49
Комментарии

Это очень прояснило ситуацию, спасибо. Как раз искал такое решение. Если бы вопрос не касался только "названия типа записи", этот ответ заслуживал бы голоса.

Jonas Lundman Jonas Lundman
21 окт. 2017 г. 21:36:51

Да! $post_type_link = get_post_type_archive_link( get_query_var( 'post_type' ) ); — это именно то, что мне было нужно.

squarecandy squarecandy
25 нояб. 2020 г. 19:11:27
1

Вы можете использовать этот код, и он работает у меня,

 $t_slug = get_query_var('term');
10 авг. 2016 г. 07:50:16
Комментарии

Это лучше, чем get_post_type(), так как этот метод вернёт правильное значение даже если архив пуст

cameronjonesweb cameronjonesweb
29 мар. 2021 г. 08:11:48
0

Следует отметить, что если при регистрации пользовательского типа записи has_archive установлен в true, архив типа записи /cptslug/ будет внутренне переписан в ?post_type=cptslug. Это также означает, что is_post_type_archive() вернет true.

К сожалению, если зарегистрированный слаг перезаписи отличается от типа записи, вы не сможете надежно получить post_type. Например, если ваш тип записи — myplugin_cars, а слаг перезаписи — cars, и вам нужно получить именно myplugin_cars, то даже этот код (чтобы избежать ошибок, если текущий запрашиваемый объект не является пользовательским типом записи) всё равно не сработает:

$queryobject = get_queried_object();
if (has_property('rewrite',$queryobject)) {
    if (isset($queryobject->rewrite['slug'])) {
         $posttype = $queryobject->rewrite['slug'];
     }
 }

Но поскольку is_post_type_archive возвращает true, этот способ более надежен:

if (is_post_type_archive()) {
    $posttype = get_query_var('post_type');
    // что по сути то же самое, что:
    // global $wp_query;
    // $posttype = $wp_query->query_vars['post_type'];
} 
else ($posttype = 'post';}

Но подождите, есть ещё кое-что... Оказывается, после небольшого тестирования всё не так просто... Что, если вы находитесь на странице архива таксономии с несколькими типами записей? Или присвоили метки записи пользовательскому типу, отличному от post? Или находитесь на странице архива автора? Архива по дате? ...или даже используете сложный tax_query или meta_query для WP_Query?

Единственный надежный способ (без проверки всех возможных случаев архива) — это перебрать фактические записи в запросе... Вот полная функция, которую я разработал, чтобы она работала как на отдельных страницах, так и на архивах, позволяя при необходимости передавать пользовательский объект запроса (или объект записи/ID записи для отдельных записей):

function get_current_post_types($object=null) {

    // если передано числовое значение, считаем его ID записи
    if ( ($object) && (is_numeric($object)) ) {$object = get_post($object);}
    // если передан объект, считаем его объектом записи
    if ( ($object) && (is_object($object)) ) {return get_post_type($object);}

    // стандартные проверки типа записи для отдельных страниц
    if (is_404()) {return '';}
    // обновление: убрал эту проверку, обрабатывается is_singular
    // if (is_single()) {return 'post';}
    if (is_page()) {return 'page';}
    if (is_attachment()) {return 'attachment';}
    if (is_singular()) {return get_post_type();}

    // если пользовательский объект запроса не передан, используем глобальный $wp_query
    if ( (!$object) || (!is_object($object)) ) {
        global $wp_query; $object = $wp_query;
    }
    if (!is_object($object)) {return '';} // на всякий случай

    // если переменная запроса post_type была явно установлена
    // (или неявно установлена для CPT через редирект has_archive)
    // то есть это верно как минимум для is_post_type_archive
    // $vqueriedposttype = get_query_var('post_type'); // только для $wp_query
    if (property_exists($object,'query_vars')) {
        $posttype = $object->query_vars['post_type'];
        if ($posttype) {return $posttype;}
    }

    // обработка всех остальных случаев путем перебора записей в объекте запроса
    $posttypes = array();
    if (method_exists($object,'found_posts')) {
        if ($object->found_posts > 0) {
            $queriedposts = $object->posts;
            foreach ($queriedposts as $queriedpost) {
                $posttype = $queriedpost->post_type;
                if (!in_array($posttype,$posttypes)) {$posttypes[] = $posttype;}
            }
            if (count($posttypes == 1)) {return $posttypes[0];}
            else {return $posttypes;}
         }
     }
     return ''; // ничего не найдено
}

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

$posttypes = get_current_post_types();
// или передать ID записи 
$posttypes = get_current_post_types($postid);
// или передать объект записи
$posttypes = get_current_post_types($post);
// или передать пользовательский запрос, который уже выполнен
$posttypes = get_current_post_types($query);

Пример использования (просто для развлечения):

add_filter('the_posts','myplugin_fading_thumbnails',10,2);
function myplugin_fading_thumbnails($posts,$query) {
    if (!is_archive()) {return $posts;}
    $cptslug = 'myplugin_slug'; $dosomethingcool = false;
    $posttypes = get_current_post_types($query);
    if ( (is_array($posttypes)) && (in_array($cptslug,$posttypes)) ) {$dosomethingcool = true;}
    elseif ($cptslug == $posttypes) {$dosomethingcool = true;}

    if ($dosomethingcool) {
        global $fadingthumbnails; $fadingthumbnails = $cptslug;
        if (!has_action('wp_footer','myplugin_cpt_script')) {
            add_action('wp_footer','myplugin_cpt_script');
        }
    }

    function myplugin_cpt_script() {
        global $fadingthumbnails;
        echo "<script>var thumbnailclass = 'img.thumbtype-".$fadingthumbnails."';
        function fadeoutthumbnails() {jQuery(thumbnailclass).fadeOut(3000,fadeinthumbnails);}
        function fadeinthumbnails() {jQuery(thumbnailclass).fadeIn(3000,fadeoutthumbnails);}
        jQuery(document).ready(function() {fadeoutthumbnails();});
        </script>";
    }

    return $posts;
 }

Чтобы увидеть эффект, измените пользовательский тип записи в коде на post и добавьте атрибут класса thumbtype-post к вашим миниатюрам записей...

6 июн. 2016 г. 21:53:05
3

Вы можете использовать этот код:

$queried_object = get_queried_object();
$posttype_slug = $queried_object->query_var;
echo $posttype_slug;

Используйте переменную $posttype_slug по вашему усмотрению

3 июн. 2016 г. 17:42:57
Комментарии

для этого нужно $queried_object->query_var['post_type'];, чтобы работало...

majick majick
6 июн. 2016 г. 21:57:25

Нет. $queried_object->query_var содержит только строку типа записи. Это не объект и не массив. Посмотрите на это изображение: http://prntscr.com/bd58e1

Guy Ytzhak Guy Ytzhak
6 июн. 2016 г. 22:33:58

ок, но только если запрошенный объект точно является объектом произвольного типа записи, вы получите другой соответствующий объект и, следовательно, пустое значение для архивных страниц категорий/таксономий/меток/авторов, например. Даже для ?post_type=post я получаю пустое значение. Сравните с get_query_var('post_type');

majick majick
6 июн. 2016 г. 23:31:21
0
-4
if( get_post_type( get_the_ID() ) == 'projects' )
{
  //вставить код для этого типа записи
}
13 мар. 2014 г. 06:22:18