Obtener el slug del tipo de entrada personalizada para una página de archivo
¿Cómo puedo descubrir el slug del tipo de entrada personalizada cuando estoy en una página de archivo?
Por ejemplo, si /products/
activa la plantilla archive-products.php
, ¿cómo obtengo (pragmáticamente) el slug del tipo de entrada?
Gracias
Para obtener el tipo de publicación actual usa get_post_type()
. Luego solicita a get_post_type_object()
todos los datos que necesites, por ejemplo el 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;
}

Creo (no lo he probado) que get_queried_object()
obtendría la misma información con menos pasos.

@Rarst Quizás, pero creo que el código que sugerí es más fácil de entender.

La solución de Toscho es incorrecta, porque get_post_type devuelve el tipo de post de la página actual y, cuando estás en una página de archivo, esta función siempre devuelve "page". Estoy buscando resolver lo mismo: Cuando estoy en la página de archivo de 'libros' (por ejemplo), quiero que devuelva: 'libros'. Cuando lo consiga lo publicaré.

desafortunadamente no es tan simple, aunque estarías mejor con solo $posttype = get_query_var('post_type');
... he agregado una alternativa más completa.

No creo que esta respuesta cubra toda la historia. Deberías verificar las reglas de reescritura de instalación ya que muchos filtros (como la página de tienda de woocommerce) están haciendo cambios. Usa el mecanismo propio de WordPress en su lugar, mira mi respuesta más abajo.

Estoy usando esto fuera del loop en la plantilla archive.php para obtener en qué archivo de posts personalizados me encuentro.
Es una combinación de los métodos que recomendaron tanto @toscho como @Rarst:
$post_type = get_queried_object();
echo $post_type->rewrite['slug'];
Actualización: @majick señaló que esto solo funciona si has establecido el slug de reescritura para tu CPT. El slug de reescritura es opcional al registrar un CPT y por defecto usa post_type si no está configurado.

cuando intenté esto obtuve Notice: Undefined property: stdClass::$rewrite in ***\wp-content\themes\marks-remarks\archive.php on line 4

esto solo funcionará si el slug de reescritura está configurado para el CPT registrado, ya que es opcional y por defecto usa el post_type

¡Gracias por detectar eso @majick! He actualizado la publicación para reflejar tu información.

Las respuestas se vuelven confusas. Y quizás yo también lo esté, pero la pregunta del título es:
Obtener el slug de un tipo de entrada personalizado para una página de archivo
Si te refieres a la página de destino del archivo de tipo de entrada, y cuando is_post_type_archive()
devuelve true
, quieres el slug que corresponde al archivo actual que se está visualizando:
/* devuelve /products/ */
$responding_name = str_replace(get_home_url(), '', get_post_type_archive_link(get_query_var('post_type')));
/* continuar para obtener 'products' sin las barras del slug */
$responding_name = str_replace('/', '', $responding_name);
-- FIN DE LA RESPUESTA A LA PREGUNTA --
Explicación:
No puedes depender del slug registrado. WordPress tampoco lo hace. Por ejemplo, al llamar a get_post_type_archive_link()
, WordPress verifica las reglas de reescritura actuales para tu instalación.
Dondequiera que estés, dentro o fuera del loop, en un archivo actual o en una entrada individual, revierte el mecanismo de get_post_type_archive_link()
. (Permalinks activados.)
Consideraciones:
Como se menciona aquí, el/los tipo(s) de entrada en la consulta actual pueden ser un array
. Puedes profundizar con tus intenciones filtrando el tipo de entrada que buscas, por ejemplo:
$post_type = get_query_var('post_type');
if(is_array($post_type)) $post_type = reset($post_type);
o
if(isset($post_types[0])) $post_type = $post_types[0];
Otro punto de vista:
Ejemplo de WooCommerce, que está registrado con el tipo de entrada 'products' pero en realidad usa un nombre de regla reescrita (shop):
/* devuelve shop */
$responding_name = str_replace('/', '', str_replace(get_home_url(), '', get_post_type_archive_link('product')));
Mark, estoy usando
$responding_name
, porque los objetivos pueden variar. Un archivo de entrada no existe, es solo una URL.

Esto lo dejó muy claro, gracias. Estaba buscando esta solución. Si la pregunta no buscaba "solo el nombre del tipo de publicación", esta debería ser una respuesta votada.

Debe tenerse en cuenta que si has_archive
se establece como verdadero al registrar el Custom Post Type, el archivo del tipo de contenido /cptslug/
se reescribirá internamente como ?post_type=cptslug
. Esto también significa que is_post_type_archive()
devolverá verdadero.
Desafortunadamente, cuando el slug de reescritura registrado es diferente al tipo de post, no se obtiene de manera confiable el post_type
. Por ejemplo, si tu tipo de post era myplugin_cars
y tu slug de reescritura era cars
, y necesitas obtener myplugin_cars
, incluso esto (para evitar errores si el objeto consultado actualmente no es un custom post type) seguirá fallando:
$queryobject = get_queried_object();
if (has_property('rewrite',$queryobject)) {
if (isset($queryobject->rewrite['slug'])) {
$posttype = $queryobject->rewrite['slug'];
}
}
Pero como is_post_type_archive
es verdadero, esto es más confiable:
if (is_post_type_archive()) {
$posttype = get_query_var('post_type');
// que es básicamente lo mismo que:
// global $wp_query;
// $posttype = $wp_query->query_vars['post_type'];
}
else ($posttype = 'post';}
Pero espera, hay más... resulta que con un poco de pruebas no es tan simple... ¿qué pasa si estás en una página de archivo de taxonomía con múltiples tipos de post en la taxonomía? ¿O asignas etiquetas de post a un custom post type diferente a 'post'? ¿O estás en una página de archivo de autor? ¿Página de archivo por fecha? ...¿o incluso tienes un tax_query
o meta_query
complejo para WP_Query
?
La única respuesta confiable (sin probar todos los casos posibles de archivo) es recorrer los posts reales en la consulta... Aquí está la función completa que desarrollé para trabajar tanto en páginas singulares como de archivo, permitiéndote opcionalmente pasar un objeto de consulta personalizado (u objeto de post/ID de post para posts singulares):
function get_current_post_types($object=null) {
// si se pasa un valor numérico, asumir que es un ID de post
if ( ($object) && (is_numeric($object)) ) {$object = get_post($object);}
// si se pasa un objeto, asumir que es un objeto post
if ( ($object) && (is_object($object)) ) {return get_post_type($object);}
// comprobaciones estándar de tipo de post singular
if (is_404()) {return '';}
// actualización: eliminada esta comprobación, manejada por is_singular
// if (is_single()) {return 'post';}
if (is_page()) {return 'page';}
if (is_attachment()) {return 'attachment';}
if (is_singular()) {return get_post_type();}
// si no se pasó un objeto de consulta personalizado, usar $wp_query global
if ( (!$object) || (!is_object($object)) ) {
global $wp_query; $object = $wp_query;
}
if (!is_object($object)) {return '';} // no debería fallar
// si la variable de consulta post_type ha sido establecida explícitamente
// (o implícitamente en el CPT via una redirección has_archive)
// es decir, esto es verdadero al menos para is_post_type_archive
// $vqueriedposttype = get_query_var('post_type'); // solo $wp_query
if (property_exists($object,'query_vars')) {
$posttype = $object->query_vars['post_type'];
if ($posttype) {return $posttype;}
}
// manejar otros casos recorriendo posts en el objeto de consulta
$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 ''; // nada que ver aquí
}
Esto devolverá de manera confiable (¿dije eso?) un array de tipos de post si hay más de uno presente, o un string con el tipo de post único si solo hay uno. Todo lo que necesitas hacer es:
$posttypes = get_current_post_types();
// o pasar un ID de post
$posttypes = get_current_post_types($postid);
// o pasar un objeto post
$posttypes = get_current_post_types($post);
// o pasar una consulta personalizada - que se haya ejecutado
$posttypes = get_current_post_types($query);
Ejemplo de uso (solo por diversión):
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;
}
Para ver el efecto, cambia el custom post type en el código a post
, y añade un atributo de clase thumbtype-post
a tus imágenes miniatura de posts...

Puedes usar este código:
// Obtener el objeto de la consulta actual
$queried_object = get_queried_object();
// Obtener el slug del tipo de post
$posttype_slug = $queried_object->query_var;
// Mostrar el slug del tipo de post
echo $posttype_slug;
Usa la variable $posttype_slug para lo que necesites

necesita $queried_object->query_var['post_type'];
para que esto funcione...

No. $queried_object->query_var contiene solo el string del tipo de post. No es un objeto o array. Mira esta imagen: http://prntscr.com/bd58e1

ok pero solo si el objeto consultado es definitivamente un objeto de tipo de post personalizado, obtendrás un objeto correspondiente diferente y por lo tanto un valor vacío para páginas de archivo de categoría/taxonomía/etiqueta/autor por ejemplo. Incluso para ?post_type=post
obtengo vacío. Compara con get_query_var('post_type');
