web-dev-qa-db-fra.com

Listes d’archives filtrées par date dans un champ personnalisé/Post Meta?

( Note du modérateur: Le titre d'origine était "utiliser archive par date avec une date personnalisée")

J'ajoute une date supplémentaire aux publications en tant que champ personnalisé. Maintenant, je veux que les archives affichent les messages par date personnalisée et non par date publiée. Par exemple, j'ai un article publié aujourd'hui (22 décembre) mais la date personnalisée est définie sur 1er janvier . Lorsque je charge l'URL archives/date/2011/01 dans le navigateur, les publications dont la date personnalisée correspond ne sont pas affichées (évidemment).

Existe-t-il un moyen de modifier le comportement de la page générée pour l'URL archives/date/2011/01 afin de récupérer les publications à la date personnalisée?

Merci.

4
Dalen

Comme avec beaucoup de choses dans WordPress, il y a plusieurs façons de faire ce que vous voulez. Je vais expliquer l'un d'entre eux.

Supprimer les variables de requête 'year', 'monthnum' et 'day'

Vous pouvez modifier les paramètres de la requête utilisée par WordPress sur les URL d'archive à l'intérieur du crochet 'pre_get_posts'. Ces paramètres sont capturés sous forme de tableau associatif par les règles de réécriture dans la propriété de l'objet WP_Query appelé query_vars variables 'year', 'monthnum' et 'day'.

Lorsque $wp_query->query_vars a des valeurs pour 'year', 'monthnum' et 'day', WordPress les utilisera pour interroger la liste des publications so la première étape consiste à supprimer ces paires clé-valeur du tableau de requêtes en utilisant la fonction unset() de PHP (notez que $wp_query est une variable globale dans WordPress qui contient l'objet de requête actuel en tant qu'instance de la classe WP_Query.)

La fonction yoursite_pre_get_posts() ci-dessous déclenchée par le hook 'pre_get_posts' supprimera ces variables du tableau query_vars, mais uniquement lorsque la requête est la requête principale * (c.-à-d. Le $query transmis au hook est exactement égal au global $wp_the_query ou $query===$wp_the_query) et uniquement lorsque la requête est une archive requête. Si vous ajoutez ceci au fichier functions.php de votre thème, vos pages d'archives affichent tous les articles, pas seulement ceux de la date (nous sommes donc à mi-chemin de ce que vous voulez ...) :

add_action('pre_get_posts', 'yoursite_pre_get_posts' );
function yoursite_pre_get_posts( $query ) {
  global $wp_the_query;
  if ($query===$wp_the_query && $query->is_archive) {
    unset($query->query_vars['year']);
    unset($query->query_vars['monthnum']);
    unset($query->query_vars['day']);
  }
}

Ajouter des variables de requête pour votre champ personnalisé

C'est maintenant que ça devient un peu délicat. Dans v3.0.x, WordPress ne vous permet que de rechercher un champ personnalisé à l'aide des valeurs du tableau query_var et ne nous permet pas non plus d'appliquer de fonctions à ces critères.

La modification suivante apportée à yoursite_pre_get_posts() permettrait à votre requête d'archivage de correspondre à une date exacte en supposant que vous la stockiez au format 'YYYY-MM-DD' dans le champ personnalisé:

add_action('pre_get_posts', 'yoursite_pre_get_posts' );
function yoursite_pre_get_posts( $query ) {
  global $wp_the_query;
  if ($query===$wp_the_query && $query->is_archive) {
    $qv = &$query->query_vars;
    $date = mktime(0,0,0,$qv['monthnum'],$qv['day'],$qv['year']);
    $qv['meta_key'] = 'Custom Date';
    $qv['meta_value'] = date("Y-m-d",$date);
    unset($qv['year']);
    unset($qv['monthnum']);
    unset($qv['day']);
  }
}

Et voici à quoi cela ressemble dans une capture d'écran:

Bien sûr, ce n'est pas vraiment ce que vous voulez. Vous souhaitez interroger l'année et le mois au lieu du jour spécifique ou même de l'année. Comme je l'ai déjà dit, c'est là que ça devient difficile.

Utilisez le crochet 'posts_where' pour modifier la clause WHERE SQL

En gros, vous devez aller plus loin dans les crochets et appeler le crochet 'posts_where', ce que j’essaie toujours d’éviter, si possible. En effet, lorsque vous effectuez une recherche textuelle sur des fragments de requête SQL, il est très facile d’écrire du code incompatible avec un autre plugin. modifie la même requête SQL. Néanmoins, si vous en avez besoin et que rien d’autre ne fonctionnera, c’est là pour vous en dernier recours.

Ainsi, la fonction yoursite_posts_where() recherche dans la clause WHERE que WordPress construit pour le texte "AND wp_postmeta.meta_value = '2011-01'" et le remplace par le texte "AND SUBSTRING(wp_postmeta.meta_value,1,7) = '2011-01'", et voici le code:

add_action('posts_where','yoursite_posts_where',10,2);
function yoursite_posts_where( $where, $query ) {
  global $wp_the_query;
  if ($query===$wp_the_query && $query->is_archive) {
    $meta_value = $query->query_vars['meta_value'];
    $length = strlen($meta_value);
    $find = "AND wp_postmeta.meta_value = '{$meta_value}'";
    $replace = "AND SUBSTR(wp_postmeta.meta_value,1,{$length}) = '{$meta_value}'";
    $where = str_replace($find,$replace,$where);
  }
  return $where;
}

Modifier yoursite_pre_get_posts() pour prendre en charge plusieurs options année-mois-jour

Bien sûr, cela nécessitera que nous modifions notre fonction yoursite_pre_get_posts() pour prendre en charge différentes méta-valeurs de longueur: 'YYYY', 'YYYY-MM' et 'YYYY-MM-DD' (Notez que l'utilisation de ce qui semble être une utilisation complexe des fonctions mktime() et date() de PHP sert simplement à éviter de s'inquiéter ces modèles: 'YYYY-M', 'YYYY-MM-D' et 'YYYY-M-D'):

add_action('pre_get_posts','yoursite_pre_get_posts' );
function yoursite_pre_get_posts( $query ) {
  global $wp_the_query;
  if ($query===$wp_the_query && $query->is_archive) {
    $qv = &$query->query_vars;  // Make it less tedious to reference
    if ($qv['monthnum']==0) // Just search on YYYY
      $date = $qv['year'];
    else if ($qv['day']==0) // Search on YYYY-MM
      $date = date('Y-m',mktime(0,0,0,$qv['monthnum'],1,$qv['year']));
    else
      $date = date('Y-m-d',mktime(0,0,0,$qv['monthnum'],$qv['day'],$qv['year']));
    $qv['meta_key'] = 'Custom Date';
    $qv['meta_value'] = $date;
    unset($qv['year']);
    unset($qv['monthnum']);
    unset($qv['day']);
  }
}

Et cela nous donne le texte suivant qui résume assez bien ce que vous cherchiez:

Code pour afficher la date personnalisée dans le thème

BTW, voici le code que j'ai utilisé dans le thème pour récupérer la méta valeur Custom Date:

<?php if ($custom_date = get_post_meta($post->ID,'Custom Date',true)): ?>
  <h2>Custom Date: <?php echo $custom_date; ?></h2>
<?php endif; ?>

P.S. Rappelez-vous que l'utilisateur doit entrer au format 'YYYY-MM-DD'

Rappelez-vous que l'utilisateur doit entrer la date personnalisée au format 'YYYY-MM-DD' pour que cela fonctionne. Bien sûr, vous pouvez le rendre plus convivial pour l’utilisateur via différentes méthodes, c’est-à-dire dans le code SQL ou via un crochet 'save_post' qui reformate la date, mais je laisserai cela comme un exercice pour quelqu'un d'autre.

P.P.S. Option: enregistrer plusieurs méta-valeurs à la place

Une autre approche aurait consisté à utiliser le crochet 'save_post' pour enregistrer trois (3) méta-valeurs cachées dans le bon format afin de les mettre en correspondance avec 'YYYY-MM-DD', 'YYYY-MM' et 'YYYY', éventuellement avec les méta-clés '_custom_date', '_custom_date_year_month''_custom_date_year', ce qui serait plus résistant aux autres plugins souhaitons également modifier la clause SQL WHERE mais ajouteraient trois (3) champs personnalisés masqués supplémentaires pour chaque publication, de sorte que ce ne serait peut-être pas une bonne idée pour un blog comportant un grand nombre de publications et qu'il soit possible qu'elles ne se synchronisent pas .

9
MikeSchinkel

Oui, vous devrez soit utiliser query_posts() ou get_posts() ou écrire vous-même une requête personnalisée.

0
Mark

Essaye ça:

PS hm, je pense que les archives de date sont généralement du type /year/month/, que faites-vous pour obtenir le /archives/date/year/month/? ..

PPS en fait, après avoir examiné la réponse de Mike, cela n’est probablement pas suffisant pour affecter la sélection des postes. Grattez ça.

0
Rarst