WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How do I discover the custom post type slug when I'm on an archive page?

For instance if /products/ fires the archive-products.php template, how (pragmatically) do I get the post type slug?

Thanks

share|improve this question

To get the current post type use get_post_type(). Then ask get_post_type_object() for all the data you need, for example the 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;
}
share|improve this answer
    
I think (hadn't tested) get_queried_object() would get to same info in less moves. – Rarst Oct 9 '12 at 1:15
    
@Rarst Maybe, but I think the code I suggested is easier to understand. – toscho Oct 9 '12 at 1:18
1  
Toscho's solutions is wrong, because get_post_type returns the post type of current page, and, when you are into archive page, this function alwasy return "page". I'm sarching to solve the same: When I am into archive page of 'books' (4 example), I want this: 'books'. When I get it I'll post it. – eMarine Jun 25 '13 at 9:58
    
unfortunately it's not that simple, though you'd be better off with just $posttype = get_query_var('post_type'); ... I've added a comprehensive alternative. – majick Jun 6 at 18:56

I'm using this outside of the loop on the archive.php template to get which custom post archive I'm on.

It's a combo of the methods that both @toscho and @Rarst recommended:

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

Update: @majick pointed out that this only works if you've set the rewrite slug for your CPT. Rewrite slug is optional when registering a CPT and defaults to post_type if not set.

share|improve this answer
    
when I tried this I got Notice: Undefined property: stdClass::$rewrite in ***\wp-content\themes\marks-remarks\archive.php on line 4 – patrickzdb Oct 20 '15 at 13:37
    
this will only work if the rewrite slug is set for the registered CPT, as it is optional and defaults to the post_type – majick Jun 3 at 3:23
    
Thanks for catching that @majick! I've updated the post to reflect your info. – Jerry Jun 3 at 14:23
    
turns out that was the tip of the iceberg... check my new answer for the underwater part :-) – majick Jun 6 at 18:53

You can use this code:

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

use $posttype_slug var whatever you need

share|improve this answer
    
it needs to $queried_object->query_var['post_type']; for this to work... – majick Jun 6 at 18:57
    
No. $queried_object->query_var containe only string of post type. it's not object or array. look at this image: prntscr.com/bd58e1 – Guy Ytzhak Jun 6 at 19:33
    
ok but only if the queried object is definitely a custom post type object, you will get a different corresponding object and thus empty value for category/tax/tag/author archive pages for example. even for ?post_type=post I get empty. compare with get_query_var('post_type'); – majick Jun 6 at 20:31

t should be noted that if has_archive is set to true while registering the Custom Post Type, the post type archive /cptslug/ will be internally rewritten to ?post_type=cptslug. So this would also mean is_post_type_archive() will return true.

Unfortunately, where the registered rewrite slug is different to the post type, you are not actually reliably getting the post_type. eg. if your post type was myplugin_cars and your rewrite slug was cars and you need to be getting myplugin_cars then even this (to prevent errors if the current queried object is not a custom post type) will still fail:

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

But because is_post_type_archive is true this is more reliable:

if (is_post_type_archive()) {
    $posttype = get_query_var('post_type');
    // which is basically the same as:
    // global $wp_query;
    // $posttype = $wp_query->query_vars['post_type'];
} 
else ($posttype = 'post';}

But hang on, there's more... turns out with a little testing it really isn't that simple either... what if you are on a taxonomy archive page with multiple post types in the taxonomy..? Or assign post tags to a custom post type other than post? Or are on an author archive page? Date archive page? ...or even have a complex tax_query or meta_query for WP_Query?

The only reliable answer (without testing for every possible archive case) is to loop the actual posts in the query... Here is the full function I came up with to work on both singular and archive pages, and allowing you to optionally pass a custom query object (or post object/post ID for singular posts):

function get_current_post_types($object=null) {

    // no post type for a 404
    if (is_404()) {return '';}

    // standard single post type checks
    if (is_single()) {return 'post';}
    if (is_page()) {return 'page';}
    if (is_attachment()) {return 'attachment';}
    if (is_singular()) {
        // if a numeric value passed, assume it is a post ID
        if ( ($object) && (is_numeric($object)) ) {$object = get_post($object);}
        // if an object is passed on singular post/page, assume a post object
        if ( ($object) && (is_object($object)) ) {return get_post_type($object);}
        return get_post_type();
    }

    // if a custom query object was not passed, use $wp_query global
    if ( (!$object) || (!is_object($object)) ) {
        global $wp_query; $object = $wp_query;
    }
    if (!is_object($object)) {return '';} // should not fail

    // if the post_type query var has been explicitly set
    // (or implicitly set on the cpt via a has_archive redirect)
    // ie. this is true for is_post_type_archive at least
    // $vqueriedposttype = get_query_var('post_type'); // $wp_query only
    if (property_exists($object,'query_vars')) {
        $posttype = $object->query_vars['post_type'];
        if ($posttype) {return $posttype;}
    }

    // handle all other cases by looping posts in query object
    $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 ''; // nothin to see here
}

This will reliably (did I say that?) return an array of post types if more than one is present, or a string with the single post type if there is only one type. All you need to do is:

$posttypes = get_current_post_types();
// or pass a post ID 
$posttypes = get_current_post_types($postid);
// or pass a post object
$posttypes = get_current_post_types($post);
// or pass a custom query - that has been run
$posttypes = get_current_post_types($query);

Example Usage (just for fun):

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;
 }

To see the effect, change the custom post type in the code to post, and add a thumbtype-post class attribute to your post thumbnail images...

share|improve this answer
if( get_post_type( get_the_ID() ) == 'projects' )
{
  //enter code for this post type
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.