web-dev-qa-db-fra.com

Groupe de messages par première lettre de titre

Je travaille sur un site Web qui utilise les publications pour gérer les articles de glossaire similaires à l'exemple de site Web ci-dessous. Je voudrais trouver un moyen d'afficher les articles par ordre alphabétique et groupés par une lettre sélectionnée (telle que la lettre "F" dans l'exemple). Je voudrais que le processus soit automatique.

Exemple de sortie souhaitée: http://www.retirementdictionary.com/glossary/f

Quelqu'un peut-il suggérer un moyen de faire cela?

3
Nohl

une fois, j’ai réalisé un projet client dans lequel je devais avoir des archives par première lettre. en repensant, je me demande si je n'aurais pas dû simplement créer une taxonomie cachée, puis sauvegarder la première lettre en tant que terme de cette taxonomie.

de toute façon, voici ce que j'ai réellement fait:

/*
 * Function Create Array of Letters that have post titles (for archive)
 */

/* When the post is saved, saves our custom data */
function kia_save_first_letter( $post_id ) {
    // verify if this is an auto save routine. 
    // If it is our form has not been submitted, so we dont want to do anything
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
        return;

    //check location (only run for posts)
    $limitPostTypes = array('post');
    if (!in_array($_POST['post_type'], $limitPostTypes)) return;

    // Check permissions
    if ( !current_user_can( 'edit_post', $post_id ) )
        return;


    // OK, we're authenticated: we need to find and save the data
    $alphabet = get_option( 'kia_alphabet_archive' );

    $alphabet = is_array($alphabet) ? $alphabet : array($alphabet);

    // pop off first letter of post title
    $letter = substr($_POST['post_title'], 0, 1);

    // if it doesn't exist, add it to array
    if(!in_array($letter, $alphabet))
        $alphabet[] = $letter;
        sort($alphabet);

    $alphabet = is_array($alphabet) ? array_unique($alphabet) : array($alphabet);

    update_option( 'kia_alphabet_archive', $alphabet );
}
add_action( 'save_post', 'kia_save_first_letter' );

si vous avez déjà écrit des articles avant de les ajouter, vous devrez lancez le programme suivant une fois pour récupérer les premières lettres des messages existants:

//create array from existing posts
function kia_run_once(){
    $alphabet = array();
    $posts = get_posts(array(   
            'numberposts'     => -1
            ) );

    foreach($posts as $p) :  
        $alphabet[] = strtoupper(substr($p->post_title, 0, 1)); //first letter of post title, capitalized 
    endforeach;

    sort($alphabet);

    update_option( 'kia_alphabet_archive', array_unique($alphabet) );

}
add_action('init','kia_run_once');

Nous avons maintenant besoin de trucs à déchiffrer quand nous sommes sur une page d'archive personnalisée et quoi faire différemment

/*
 * Custom Archives by KIA
 */

function archive_queryvars( $qvars ) {
    $qvars[] = 'showarchive';
    return $qvars;
}
add_filter('query_vars', 'archive_queryvars' );


function is_custom_archive() {
    global $wp_query;
    return isset( $wp_query->query_vars['showarchive'] );
}

function archive_search_where( $where ){
    global $wpdb;

    if( is_custom_archive() ) {
        $char = get_query_var('showarchive');
        if ( ! empty($char) ) {
            $where .= "AND {$wpdb->posts}.post_title LIKE '{$char}%'";
        }
    } 
  return $where;
}
add_filter('posts_where', 'archive_search_where' );

petite fonction d'aide pour faire des liens

/* 
 * add archive query arg to link
 */
function get_custom_archive_link($char = '') {
    $params = array(
            'showarchive' => $char,
            );
    return add_query_arg( $params, home_url('/') );
}

Créez maintenant notre menu d'archives personnalisé

$alphabet = get_option ('kia_alphabet_archive');

if(count($alphabet)>0){ ?>
    <div id="archive-menu" class="menu">
    <?php for ($i=65; $i < 91; $i++) : 
            $current = (chr($i) == get_query_var('showarchive')) ? "current-menu-item" : "menu-item";

            if (is_array($alphabet) && in_array(chr($i), $alphabet)){ ?>
                <li class="az-char <?php echo $current;?>">
                    <?php printf('<a href="%s">%s</a>', get_custom_archive_link(chr($i)), chr($i) ) ?>
                </li>
            <?php } else { ?>
                <li class="az-char <?php echo $current;?>">
                    <?php echo chr($i); ?>
                </li>
            <?php } ?>  

            <?php endfor; ?>
    </div>
<?php }

le fait de cliquer sur les liens devrait maintenant vous amener à une page qui ne montre que les messages qui portent cette lettre.


en regardant en arrière, je pense que l’idée de la taxonomie consisterait en beaucoup moins de code et aurait un support de réécriture plus propre intégré depuis le début (c’est-à-dire… pas de vars de requête, même si ceux-ci pourraient être réécrits… ). l'approche taxonomique ajouterait également des données fiscales à la base de données, alors que cela n'ajoute qu'une option. donc compromis?

*EDIT**

ok, je me suis lancé dans la taxonomie et il est légèrement plus élégant que prévu

d'abord enregistrer la taxonomie. Je ne l’utilise que sur les posts, mais vous pouvez facilement le modifier pour suivre le type de post que vous souhaitez.

// Add new taxonomy, NOT hierarchical (like tags)
function kia_create_glossary_taxonomy(){
    if(!taxonomy_exists('glossary')){
        register_taxonomy('glossary',array('post'),array(
        'show_ui' => false
      ));
     }
}
add_action('init','kia_create_glossary_taxonomy');

fonction de sauvegarde similaire pour stocker nos données fiscales lorsqu’une publication est sauvegardée

/* When the post is saved, saves our custom data */
function kia_save_first_letter( $post_id ) {
    // verify if this is an auto save routine. 
    // If it is our form has not been submitted, so we dont want to do anything
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
        return;

    //check location (only run for posts)
    $limitPostTypes = array('post');
    if (!in_array($_POST['post_type'], $limitPostTypes)) return;

    // Check permissions
    if ( !current_user_can( 'edit_post', $post_id ) )
        return;


    // OK, we're authenticated: we need to find and save the data
    $taxonomy = 'glossary';

    //set term as first letter of post title, lower case
    wp_set_post_terms( $post_id, strtolower(substr($_POST['post_title'], 0, 1)), $taxonomy );

    //delete the transient that is storing the alphabet letters
    delete_transient( 'kia_archive_alphabet');
}
add_action( 'save_post', 'kia_save_first_letter' );

Encore une fois, il faut exécuter quelque chose une fois pour récupérer les anciens messages, puis les supprimer

//create array from existing posts
function kia_run_once(){
    $taxonomy = 'glossary';

    $alphabet = array();
    $posts = get_posts(array('numberposts' => -1) );

    foreach($posts as $p) :  
        //set term as first letter of post title, lower case
        wp_set_post_terms( $p->ID, strtolower(substr($p->post_title, 0, 1)), $taxonomy );
    endforeach;     
}
add_action('init','kia_run_once');

ajoutez le menu c’était la seule partie qui n’était pas tout à fait élégante, car il n’était pas simple de vérifier si un terme comportait des posts sans la boucle foreach supplémentaire. mais j'ai atténué cela en le stockant dans un transitoire qui ne réinitialise qu'à la sauvegarde.

$taxonomy = 'glossary';  

// save the terms that have posts in an array as a transient
if ( false === ( $alphabet = get_transient( 'kia_archive_alphabet' ) ) ) {
    // It wasn't there, so regenerate the data and save the transient
    $terms = get_terms($taxonomy);

    $alphabet = array();
    if($terms){
        foreach ($terms as $term){
            $alphabet[] = $term->slug;
        }
    }
     set_transient( 'kia_archive_alphabet', $alphabet );
}

?>

<div id="archive-menu" class="menu">
    <?php foreach(range('a', 'z') as $i) : 
            $current = ($i == get_query_var($taxonomy)) ? "current-menu-item" : "menu-item";

            if (in_array( $i, $alphabet )){ ?>
                <li class="az-char <?php echo $current;?>">
                    <?php printf('<a href="%s">%s</a>', get_term_link( $i, $taxonomy ), strtoupper($i) ) ?>
                </li>
            <?php } else { ?>
                <li class="az-char <?php echo $current;?>">
                    <?php echo strtoupper($i); ?>
                </li>
            <?php } ?>  

        <?php endforeach; ?>
</div>

donc il y a 2 solutions. ce dernier demandera à vos URL de dire site.com/glossary/l sans aucune règle htaccess pour réécrire les vars de requête de votre part. J'espère que cela pourra aider.

10
helgatheviking

Je vous suggérerais d'utiliser WP_Query à cette fin. Un exemple de cette requête est ici dans ce plugin qui récupère uniquement les publications pertinentes au lieu d'utiliser d'autres fonctions PHP.

Vous pouvez choisir un moyen plus rapide, Plugin Alpagetic Pagination

0