Ottenere lo slug del custom post type per una pagina di archivio
Come posso scoprire lo slug del custom post type quando mi trovo in una pagina di archivio?
Per esempio, se /products/
attiva il template archive-products.php
, come posso ottenere (programmaticamente) lo slug del post type?
Grazie

Per ottenere il tipo di post corrente usa get_post_type()
. Poi richiedi a get_post_type_object()
tutti i dati di cui hai bisogno, ad esempio lo 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;
}

Penso (non l'ho testato) che get_queried_object()
potrebbe ottenere le stesse informazioni con meno passaggi.

@Rarst Forse, ma credo che il codice che ho suggerito sia più semplice da comprendere.

La soluzione di Toscho è sbagliata, perché get_post_type restituisce il tipo di post della pagina corrente e, quando sei in una pagina di archivio, questa funzione restituisce sempre "page". Sto cercando di risolvere lo stesso problema: quando sono nella pagina di archivio di 'books' (per esempio), voglio ottenere 'books'. Quando lo risolvo, lo posterò.

purtroppo non è così semplice, anche se sarebbe meglio usare semplicemente $posttype = get_query_var('post_type');
... ho aggiunto un'alternativa più completa.

Non credo che questa risposta copra l'intera questione. Dovresti verificare le regole di rewrite installate, poiché molti filtri (come la pagina shop di WooCommerce) apportano modifiche. Usa il meccanismo integrato di WordPress invece, vedi la mia risposta più in basso.

Sto utilizzando questo codice al di fuori del loop nel template archive.php per ottenere su quale archivio di custom post mi trovo.
È una combinazione dei metodi consigliati sia da @toscho che da @Rarst:
$post_type = get_queried_object();
echo $post_type->rewrite['slug'];
Aggiornamento: @majick ha fatto notare che questo funziona solo se hai impostato lo slug rewrite per il tuo CPT. Lo slug rewrite è opzionale quando si registra un CPT e di default usa il post_type se non impostato.

quando ho provato questo ho ottenuto Notice: Undefined property: stdClass::$rewrite in ***\wp-content\themes\marks-remarks\archive.php on line 4

questo funzionerà solo se lo slug di rewrite è impostato per il CPT registrato, poiché è opzionale e di default utilizza il post_type

Grazie per averlo segnalato @majick! Ho aggiornato il post per includere la tua informazione.

Le risposte possono risultare confuse. E forse lo sono anch'io, ma la domanda principale è:
Ottenere lo slug di un custom post type per una pagina archivio
Se intendi la pagina archivio del post type, e quando is_post_type_archive()
restituisce true
, vuoi ottenere lo slug corrispondente all'archivio corrente che stai visualizzando:
/* restituisce /products/ */
$responding_name = str_replace(get_home_url(), '', get_post_type_archive_link(get_query_var('post_type')));
/* procedi per ottenere 'products' senza gli slash */
$responding_name = str_replace('/', '', $responding_name);
-- FINE DELLA RISPOSTA ALLA DOMANDA --
Spiegazione:
Non puoi affidarti allo slug registrato. Nemmeno Wordpress lo fa. Ad esempio, quando chiami get_post_type_archive_link()
, Wordpress controlla le regole di rewrite correnti per la tua installazione.
Dovunque tu sia, dentro o fuori dal loop, archivio corrente o singolo post, inverti il meccanismo di get_post_type_archive_link()
. (Con i permalink abilitati.)
Considerazioni:
Come menzionato qui, il/i post type nella query corrente possono essere un array
. Puoi andare oltre con le tue intenzioni filtrando il post type che cerchi, ad esempio:
$post_type = get_query_var('post_type');
if(is_array($post_type)) $post_type = reset($post_type);
oppure
if(isset($post_types[0])) $post_type = $post_types[0];
Un altro punto di vista:
Esempio con Woocommerce, che registra il post type object come 'products' ma in realtà utilizza una regola di rewrite diversa (shop):
/* restituisce shop */
$responding_name = str_replace('/', '', str_replace(get_home_url(), '', get_post_type_archive_link('product')));
Mark, sto usando
$responding_name
, perché gli obiettivi possono variare. Un archivio post non esiste, è solo un URL.

Questo ha reso tutto molto chiaro, grazie. Stavo cercando proprio questa soluzione. Se la domanda non avesse cercato "solo il nome del tipo di post", questa sarebbe stata la risposta più votata.

Va notato che se has_archive
è impostato su true durante la registrazione del Custom Post Type, l'archivio del post type /cptslug/
verrà riscritto internamente come ?post_type=cptslug
. Ciò significa anche che is_post_type_archive()
restituirà true.
Sfortunatamente, quando lo slug di rewrite registrato è diverso dal post type, non si ottiene in modo affidabile il post_type
. Ad esempio, se il tuo post type fosse myplugin_cars
e il tuo rewrite slug fosse cars
, e hai bisogno di ottenere myplugin_cars
, anche questo (per prevenire errori se l'oggetto corrente della query non è un custom post type) fallirà comunque:
$queryobject = get_queried_object();
if (has_property('rewrite',$queryobject)) {
if (isset($queryobject->rewrite['slug'])) {
$posttype = $queryobject->rewrite['slug'];
}
}
Ma poiché is_post_type_archive
è true, questo è più affidabile:
if (is_post_type_archive()) {
$posttype = get_query_var('post_type');
// che è sostanzialmente lo stesso di:
// global $wp_query;
// $posttype = $wp_query->query_vars['post_type'];
}
else ($posttype = 'post';}
Ma aspetta, c'è di più... si scopre con un po' di testing che non è davvero così semplice... cosa succede se sei su una pagina di archivio tassonomico con più post type nella tassonomia..? O assegni tag a un custom post type diverso da post? O sei su una pagina di archivio autore? Archivio data? ...o hai anche una complessa tax_query
o meta_query
per WP_Query
?
L'unica risposta affidabile (senza testare ogni possibile caso di archivio) è ciclare i post effettivi nella query... Ecco la funzione completa che ho creato per funzionare sia su pagine singole che di archivio, e che ti permette di passare opzionalmente un oggetto query personalizzato (o un oggetto post/ID post per post singoli):
function get_current_post_types($object=null) {
// se viene passato un valore numerico, assumi che sia un ID post
if ( ($object) && (is_numeric($object)) ) {$object = get_post($object);}
// se viene passato un oggetto, assumi che sia un oggetto post
if ( ($object) && (is_object($object)) ) {return get_post_type($object);}
// controlli standard per post type singoli
if (is_404()) {return '';}
// update: rimosso questo controllo, gestito da is_singular
// if (is_single()) {return 'post';}
if (is_page()) {return 'page';}
if (is_attachment()) {return 'attachment';}
if (is_singular()) {return get_post_type();}
// se non è stato passato un oggetto query personalizzato, usa il globale $wp_query
if ( (!$object) || (!is_object($object)) ) {
global $wp_query; $object = $wp_query;
}
if (!is_object($object)) {return '';} // non dovrebbe fallire
// se la query var post_type è stata impostata esplicitamente
// (o implicitamente sul cpt tramite un redirect has_archive)
// cioè, questo è true almeno per 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;}
}
// gestisci tutti gli altri casi ciclando i post nell'oggetto query
$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 ''; // nulla da vedere qui
}
Questo restituirà in modo affidabile (l'ho detto?) un array di post type se ce n'è più di uno, o una stringa con il singolo post type se ce n'è solo uno. Tutto ciò che devi fare è:
$posttypes = get_current_post_types();
// o passa un ID post
$posttypes = get_current_post_types($postid);
// o passa un oggetto post
$posttypes = get_current_post_types($post);
// o passa una query personalizzata - che è stata eseguita
$posttypes = get_current_post_types($query);
Esempio di Utilizzo (solo per divertimento):
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;
}
Per vedere l'effetto, cambia il custom post type nel codice in post
e aggiungi un attributo di classe thumbtype-post
alle immagini miniatura dei tuoi post...

No. $queried_object->query_var contiene solo la stringa del post type. Non è un oggetto o un array. Guarda questa immagine: http://prntscr.com/bd58e1

ok ma solo se l'oggetto interrogato è sicuramente un oggetto di custom post type, otterrai un oggetto diverso e quindi un valore vuoto per le pagine di archivio di categoria/tassonomia/tag/autore per esempio. Anche con ?post_type=post
ottengo vuoto. Confronta con get_query_var('post_type');
