按标题首字母对帖子进行分组

时间:2012-02-08 作者:Nohl

我正在一个网站上工作,该网站使用帖子作为管理词汇表文章的方式,类似于下面的示例网站。我想找到一种按字母顺序显示文章并按选定字母分组的方法(例如示例中的字母“F”)。我希望这个过程是自动的。

所需输出示例:http://www.retirementdictionary.com/glossary/f

Can anyone suggest a way to do this?

2 个回复
最合适的回答,由SO网友:helgatheviking 整理而成

有一次,我做了一个客户项目,我必须在第一封信之前就有档案。回想起来,我想知道是否应该创建一个隐藏的分类法,然后将第一个字母保存为该分类法中的术语。

anyway, here\'s what i actually did:

/*
 * 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\' );
如果您在添加此之前已经有帖子,则需要run the following once to grab the first letters for the existing posts:

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

little helper function to make links

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

now create our custom archive menu

$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 }
点击链接后,您将进入一个页面,该页面只显示带有该字母的帖子。

回顾过去,我认为分类学的想法应该是少编写很多代码,并且从一开始就内置了更干净的重写支持(即,没有查询变量,即使这些变量可以重写……我不知道怎么写)。分类法方法还将向数据库中添加税务数据,而这只添加了一个选项。那么权衡呢?

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

similar save function to store our tax data when a post is saved

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

again need to run something once to grab old posts, remove when done

//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\');
add the menu 这是唯一一个不完全优雅的部分,因为测试一个术语是否有不带额外foreach循环的post并不容易。但我通过将其存储在仅在保存后重置的瞬态中,缓解了这种情况。

$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>
因此,有两种解决方案。后者会让您的URL显示站点。com/glossary/l,无需任何htaccess规则来重新编写查询变量。希望这有帮助。

SO网友:WordPress Mechanic

我建议您使用WP_Query 为此目的。这个插件中有一个查询示例,它只获取相关帖子,而不使用其他PHP函数。

你可以选择一种更快的方式,Alphabetic Pagination Plugin

结束

相关推荐

Only show authors with posts

我以为下面的代码可以用。。。但没有骰子。类似于“AND post\\u count>0”函数贡献者(){全局$wpdb;$authors = $wpdb->get_results(\"SELECT ID, user_nicename from $wpdb->users WHERE display_name <> \'admin\' AND post_count > 0 ORDER BY display_name\"); foreach ($author