web-dev-qa-db-ja.com

タイトルの最初の文字でグループ投稿

私は以下の例のウェブサイトのような用語集記事を管理する方法として投稿を使っているウェブサイトに取り組んでいます。アルファベット順に記事を表示し、選択した文字(例では文字 'F')でグループ化した方法を見つけたいプロセスを自動にしたいです。

望ましい出力の例: http://www.retirementdictionary.com/glossary/f

誰もがこれを行う方法を提案できますか?

3
Nohl

かつて私は私が最初の手紙によってアーカイブを持っていなければならなかったクライアントプロジェクトをしました。振り返って考えると、単に隠された分類法を作成してから、その分類法の用語として最初の文字を保存するべきではないかと思いました。

とにかく、これが私が実際にしたことです:

/*
 * 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' );

これを追加する前にすでに投稿がある場合は、 既存の投稿の最初の文字を取得するために次のコマンドを1回実行します。

//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');

今、私たちは、カスタムアーカイブページ上にあったときに何が違うのかを解読するためのいくつかのものが必要です

/*
 * 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' );

リンクを張る小さなヘルパー関数

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

カスタムアーカイブメニューを作成します

$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 }

リンクをクリックすると、その文字が含まれている投稿のみを表示するページに移動します。


振り返ってみると、タクソノミーの考え方は、はるかに少ないコードで、最初からより明確な書き換えサポートが組み込まれていると思います(つまり、クエリ変数がない場合でも、それらは書き直される可能性があります。 )分類法では税務データもDBに追加されますが、これには1つの選択肢しか追加されません。そうトレードオフ?

* _ edit _ **

わかりました、私は分類法のルートで突き刺しをしました、そして私が予想したようにそれはもう少しエレガントです

最初に分類法を登録します。私はこれを投稿でのみ実行していますが、あなたが好きな投稿の種類に合わせて簡単に変更することができます。

// 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');

投稿が保存されたときに私たちの税データを保存するための同様の保存機能

/* 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' );

古い投稿をつかむためにもう一度何かを実行する必要があり、完了したら削除する

//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');

メニューを追加する ある単語に特別なforeachループのない投稿があるかどうかをテストするのは簡単ではなかったため、これは完全にエレガントではなかった唯一の部分です。しかし、私はそれをポストセーブでリセットするだけの一時的なものに保存することによってそれを軽減しました。

$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>

だから2つの解決策があります。後者はあなたの側にクエリ変数を書き直すためのいかなるhtaccess規則もなしにあなたのURLにsite.com/glossary/lを言わせるでしょう。それが役立つことを願っています。

10
helgatheviking

この目的のためにWP_Queryを使うことをお勧めします。このクエリの例は、このプラグインにあり、これはさらにPHP関数を使用する代わりに関連する投稿のみを取得します。

あなたは上に行くためのより速い方法を選ぶことができます、 アルファベットのページ付けプラグイン

0