J'ai vu beaucoup de questions/messages à ce sujet, mais je n'ai pas encore trouvé de solution décente. Fondamentalement, j'essaie de faire ce que wp_get_archives
fait, mais pour un type de publication personnalisé (personnellement, je ne sais pas pourquoi wp_get_archives
ne prend pas en charge les types de publication personnalisés!).
Le code que j'utilise actuellement est le suivant
functions.php
function Cpt_getarchives_where_filter( $where , $r ) {
$post_type = 'events';
return str_replace( "post_type = 'post'" , "post_type = '$post_type'" , $where );
}
sidebar-events.php
add_filter( 'getarchives_where' , 'Cpt_getarchives_where_filter' , 10 , 2 );
wp_get_archives();
remove_filter('getarchives_where' , 'Cpt_getarchives_where_filter' , 10 );
Ce code affiche les dates (par exemple, avril 2014, mars 2014), etc. Ce qui est formidable, mais cliquer sur les liens ne fait que placer un 404. L'URL créée pour chaque lien de date est/2014/04 /. Cependant, cela devrait être quelque chose comme/événements/2014/04 /.
Existe-t-il un moyen d'inclure des "événements" dans l'URL afin que le modèle archive-events.php puisse être utilisé, et y a-t-il une raison pour laquelle les liens génèrent actuellement un 404?
Un grand merci pour toute aide
Vous pouvez également filtrer 'month_link'
pour les archives mensuelles, 'year_link'
pour les archives annuelles et 'day_link'
pour les archives quotidiennes.
Vous pouvez également écrire une fonction qui étend wp_get_archives
pour utiliser des CPT, en ajoutant des filtres à 'getarchives_where'
et au lien d’archive.
function wp_get_cpt_archives( $cpt = 'post', $args = array() ) {
// if cpt is post run the core get archives
if ( $cpt === 'post' ) return wp_get_archives($args);
// if cpt doesn't exists return error
if ( ! post_type_exists($cpt) ) return new WP_Error('invalid-post-type');
$pto = get_post_type_object($cpt);
// if cpt doesn't have archive return error
if ( ! $pto = get_post_type_object( $cpt ) ) return false;
$types = array('monthly' => 'month', 'daily' => 'day', 'yearly' => 'year');
$type = isset( $args['type'] ) ? $args['type'] : 'monthly';
if ( ! array_key_exists($type, $types) ) {
// supporting only 'monthly', 'daily' and 'yearly' archives
return FALSE;
}
$done_where = $done_link = FALSE;
// filter where
add_filter( 'getarchives_where' , function( $where ) use (&$done_where, $cpt) {
if ( $done_where ) return $where;
return str_replace( "post_type = 'post'" , "post_type = '{$cpt}'" , $where );
});
// filter link
add_filter( "{$types[$type]}_link", function( $url ) use (&$done_link, $pto, $cpt) {
if ( $done_link ) return $url;
// if no pretty permalink add post_type url var
// if ( get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
if ( ! get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
return add_query_arg( array( 'post_type' => $cpt ), $url );
} else { // pretty permalink
global $wp_rewrite;
$slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
$base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
$home = untrailingslashit( home_url( $base ) );
return str_replace( $home, home_url( $base . $slug ), $url );
}
});
// get original echo arg and then set echo to false
$notecho = isset($args['echo']) && empty($args['echo']);
$args['echo'] = FALSE;
// get archives
$archives = wp_get_archives($args);
// prevent filter running again
$done_where = $done_link = TRUE;
// echo or return archives
if ( $notecho ) {
return $archives;
} else {
echo $archives;
}
}
Veuillez lire les commentaires en ligne pour plus d'informations sur le fonctionnement de la fonction.
Maintenant, il y a un problème. Les URL telles que /events/2014/04/
sont non reconnues par WordPress. Vous devez donc ajouter les règles de réécriture qui gèrent ce type d’URL.
Encore une fois, vous pouvez écrire une fonction qui ajoute ces règles pour vous:
function generate_cpt_archive_rules( $cpt ) {
if ( empty($cpt) || ! post_type_exists($cpt) ) return;
global $wp_rewrite;
$pto = get_post_type_object($cpt);
if ( ! $pto->has_archive ) return;
$base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
$base = trailingslashit( $base );
$slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
$year = ltrim( $base . $slug . '/([0-9]{4})/?$', '/' );
$month = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/?$', '/' );
$day = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/([0-9]{2})/?$', '/' );
$index = 'index.php?post_type=' . $cpt;
$rules[$year] = $index . '&m=$matches[1]';
$rules[$month] = $index . '&m=$matches[1]$matches[2]';
$rules[$day] = $index . '&m=$matches[1]$matches[2]$matches[3]';
$page = 2;
foreach ( array( $year, $month, $day ) as $rule ) {
$paged = str_replace( '/?$', '/page/([0-9]{1,})/?$', $rule);
$rules[$paged] = $rules[$rule] . '&paged=$matches[' . $page . ']';
$page++;
}
return $rules;
}
Cette fonction génère les règles, mais vous devez également les ajouter et les vider.
Il est maintenant recommandé de vider les règles d'activation du thème (ou du plugin) et de les enregistrer sur init, de sorte que vous devriez faire quelque chose comme:
function register_cpt_dates_rules() {
$cpts = array( 'events' );
foreach ( $cpts as $cpt ) {
foreach ( generate_cpt_archive_rules( $cpt ) as $rule => $rewrite ) {
add_rewrite_rule( $rule, $rewrite, 'top' );
}
}
}
// flushing on theme switch
add_action('after_switch_theme', function() {
register_cpt_dates_rules();
$GLOBALS['wp_rewrite']->flush_rules();
});
// registering on init
add_action( 'init', 'register_cpt_dates_rules' );
Une fois que vous avez ajouté ces fonctions à votre functions.php
(et que vous avez désactivé et réactivé votre thème pour que 'after_switch_theme'
soit exécuté), vous pouvez afficher les archives à l'aide de:
wp_get_cpt_archives( 'events' );
Et il affichera les archives de l'événement CPT, et le lien sera quelque chose de /events/2014/04/
.
Cela fonctionne aussi pour les archives annuelles ou quotidiennes:
wp_get_cpt_archives( 'events', array( 'type'=>'yearly' ) );
wp_get_cpt_archives( 'events', array( 'type'=>'daily' ) );
En utilisant mes deux fonctions, vous disposez d’un moyen extrêmement facile de faire fonctionner wp_get_archives
avec les CPT.
Notez que all le code nécessite ici PHP 5.3+.
Je pense que G.M a donné tout ce dont vous avez besoin. J'ai écrit un article blog sur la génération de permalien pour les archives de dates CPT, mais je n'ai pas encore eu le temps de récupérer l'autre partie pre_get_posts
dans un formulaire d'article blog.
Il y a essentiellement 3 pièces dans le puzzle:
/2014/04/30
, /2014/
, etc.