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
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 asked Oct 7, 2012 at 11:33 Ben EverardBen Everard 1,2885 gold badges19 silver badges34 bronze badges7 Answers
Reset to default 24To 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;
}
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.
The answers get confusing. And maybe Im as well but the headline question is:
Get custom post type slug for an archive page
If you mean post type archive landing-page, and when is_post_type_archive()
returns true
, you want the slug that responing to current viewing archive:
/* returns /products/ */
$responding_name = str_replace(get_home_url(), '', get_post_type_archive_link(get_query_var('post_type')));
/* continue to get 'products' without slug slashes */
$responding_name = str_replace('/', '', $responding_name);
-- END OF ANSWERING THE QUESTION --
Explanation:
You cant rely on the registered slug. Wordpress is not either. For example, when calling get_post_type_archive_link()
Wordpress is checking the current rewrite rules for your install .
Wherever you are, inside or outside loop, current archive or single post, reverse the get_post_type_archive_link()
mechanism. (Permalinks enabled.)
Considerations:
As mentioned here, the post type(s) in current query can be an array
. You can go futher with your intensions with filter out the post type you look for, example:
$post_type = get_query_var('post_type');
if(is_array($post_type)) $post_type = reset($post_type);
or
if(isset($post_types[0])) $post_type = $post_types[0];
Another point of view:
Woocommerce example, is registered with 'products' post type object but in reality uses rewritten rule name (shop):
/* returns shop */
$responding_name = str_replace('/', '', str_replace(get_home_url(), '', get_post_type_archive_link('product')));
Mark, Im using
$responding_name
, because the objectives might vary. A post archive does not exists, its just a url.
You can use this code and this code is working for me,
$t_slug = get_query_var('term');
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) {
// 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, assume to be a post object
if ( ($object) && (is_object($object)) ) {return get_post_type($object);}
// standard single post type checks
if (is_404()) {return '';}
// update: removed this check, handled by is_singular
// if (is_single()) {return 'post';}
if (is_page()) {return 'page';}
if (is_attachment()) {return 'attachment';}
if (is_singular()) {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...
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
if( get_post_type( get_the_ID() ) == 'projects' )
{
//enter code for this post type
}