我有两种自定义帖子类型,用于处理人们的姓名。现在,在浏览视图中,它仅按字母顺序列出所有内容,而分页将它们按数字细分,当您要查找特定人员时,这并不是非常有用。
具体来说,有人要求我为看起来像这样的人创建分页链接:
- 股份公司
- HM
- NQ
- RQ
我的问题-我不知道如何通过一个字段的首字母查询自定义帖子类型。然后,我不确定如何以这种方式创建分页。有人有什么建议吗?谢谢!
我有两种自定义帖子类型,用于处理人们的姓名。现在,在浏览视图中,它仅按字母顺序列出所有内容,而分页将它们按数字细分,当您要查找特定人员时,这并不是非常有用。
具体来说,有人要求我为看起来像这样的人创建分页链接:
我的问题-我不知道如何通过一个字段的首字母查询自定义帖子类型。然后,我不确定如何以这种方式创建分页。有人有什么建议吗?谢谢!
Answers:
有趣的问题!我通过WHERE
使用一系列post_title LIKE 'A%' OR post_title LIKE 'B%' ...
子句扩展查询来解决了该问题。您也可以使用正则表达式进行范围搜索,但是我认为数据库将无法使用索引。
这是解决方案的核心:对WHERE
子句进行过滤:
add_filter( 'posts_where', 'wpse18703_posts_where', 10, 2 );
function wpse18703_posts_where( $where, &$wp_query )
{
if ( $letter_range = $wp_query->get( 'wpse18703_range' ) ) {
global $wpdb;
$letter_clauses = array();
foreach ( $letter_range as $letter ) {
$letter_clauses[] = $wpdb->posts. '.post_title LIKE \'' . $letter . '%\'';
}
$where .= ' AND (' . implode( ' OR ', $letter_clauses ) . ') ';
}
return $where;
}
当然,您不想在查询中允许随机外部输入。这就是为什么我要进行输入清理的步骤pre_get_posts
,该步骤将两个查询变量转换为有效范围。(如果您找到解决方法,请发表评论,以便我予以纠正)
add_action( 'pre_get_posts', 'wpse18703_pre_get_posts' );
function wpse18703_pre_get_posts( &$wp_query )
{
// Sanitize input
$first_letter = $wp_query->get( 'wpse18725_first_letter' );
$last_letter = $wp_query->get( 'wpse18725_last_letter' );
if ( $first_letter || $last_letter ) {
$first_letter = substr( strtoupper( $first_letter ), 0, 1 );
$last_letter = substr( strtoupper( $last_letter ), 0, 1 );
// Make sure the letters are valid
// If only one letter is valid use only that letter, not a range
if ( ! ( 'A' <= $first_letter && $first_letter <= 'Z' ) ) {
$first_letter = $last_letter;
}
if ( ! ( 'A' <= $last_letter && $last_letter <= 'Z' ) ) {
if ( $first_letter == $last_letter ) {
// None of the letters are valid, don't do a range query
return;
}
$last_letter = $first_letter;
}
$wp_query->set( 'posts_per_page', -1 );
$wp_query->set( 'wpse18703_range', range( $first_letter, $last_letter ) );
}
}
最后一步是创建一个漂亮的重写规则,以便您可以转到example.com/posts/a-g/
或example.com/posts/a
查看所有以此字母(范围)开头的帖子。
add_action( 'init', 'wpse18725_init' );
function wpse18725_init()
{
add_rewrite_rule( 'posts/(\w)(-(\w))?/?', 'index.php?wpse18725_first_letter=$matches[1]&wpse18725_last_letter=$matches[3]', 'top' );
}
add_filter( 'query_vars', 'wpse18725_query_vars' );
function wpse18725_query_vars( $query_vars )
{
$query_vars[] = 'wpse18725_first_letter';
$query_vars[] = 'wpse18725_last_letter';
return $query_vars;
}
您可以更改重写规则模式以其他方式开始。如果这是自定义帖子类型,请确保添加&post_type=your_custom_post_type
到替换中(第二个字符串,以开头index.php
)。
添加分页链接留给读者练习:-)
like_escape()
:)
这将帮助您入门。我不知道如何在特定字母处打断查询,然后告诉WP还有另一个页面包含更多字母,但是下面的内容占了其余的99%。
不要忘记发布您的解决方案!
query_posts( array( 'orderby' => 'title' ) );
// Build an alphabet array
foreach( range( 'A', 'G' ) as $letter )
$alphabet[] = $letter;
foreach( range( 'H', 'M' ) as $letter )
$alphabet[] = $letter;
foreach( range( 'N', 'Q' ) as $letter )
$alphabet[] = $letter;
foreach( range( 'R', 'Z' ) as $letter )
$alphabet[] = $letter;
if ( have_posts() )
{
while ( have_posts() )
{
global $wp_query, $post;
$max_paged = $wp_query->query_vars['max_num_pages'];
$paged = $wp_query->query_vars['paged'];
if ( ! $paged )
$paged = (int) 1;
the_post();
$first_title_letter = (string) substr( $post->post_title, 1 );
if ( in_array( $first_title_letter, $alphabet ) )
{
// DO STUFF
}
// Pagination
if ( $paged !== (int) 1 )
{
echo 'First: '._wp_link_page( 1 );
echo 'Prev: '._wp_link_page( $paged - 1 );
}
while ( $i = 1; count($alphabet) < $max_paged; i++; )
{
echo $i._wp_link_page( $i );
}
if ( $paged !== $max_paged )
{
echo 'Next: '._wp_link_page( $paged + 1 );
echo 'Last: '._wp_link_page( $max_paged );
}
} // endwhile;
} // endif;
使用@kaiser的示例的答案,带有自定义帖子类型作为接受alpha起始和结束参数的函数。该示例显然适用于简短的项目列表,因为它不包括辅助分页。我正在发布它,因此您可以根据需要将其纳入您的想法functions.php
。
// Dr Alpha Paging
// Tyrus Christiana, Senior Developer, BFGInteractive.com
// Call like alphaPageDr( "A","d" );
function alphaPageDr( $start, $end ) {
echo "Alpha Start";
$loop = new WP_Query( 'post_type=physician&orderby=title&order=asc' );
// Build an alphabet array of capitalized letters from params
foreach ( range( $start, $end ) as $letter )
$alphabet[] = strtoupper( $letter );
if ( $loop->have_posts() ) {
echo "Has Posts";
while ( $loop->have_posts() ) : $loop->the_post();
// Filter by the first letter of the last name
$first_last_name_letter = ( string ) substr( get_field( "last_name" ), 0, 1 );
if ( in_array( $first_last_name_letter, $alphabet ) ) {
//Show things
echo "<img class='sidebar_main_thumb' src= '" .
get_field( "thumbnail" ) . "' />";
echo "<div class='sidesbar_dr_name'>" .
get_field( "salutation" ) . " " .
get_field( 'first_name' ) . " " .
get_field( 'last_name' ) . "</div>";
echo "<div class='sidesbar_primary_specialty ' > Primary Specialty : " .
get_field( "primary_specialty" ) . "</div>";
}
endwhile;
}
}
这是一种使用query_vars
和posts_where
过滤器的方法:
public function range_add($aVars) {
$aVars[] = "range";
return $aVars;
}
public function range_where( $where, $args ) {
if( !is_admin() ) {
$range = ( isset($args->query_vars['range']) ? $args->query_vars['range'] : false );
if( $range ) {
$range = split(',',$range);
$where .= "AND LEFT(wp_posts.post_title,1) BETWEEN '$range[0]' AND '$range[1]'";
}
}
return $where;
}
add_filter( 'query_vars', array('atk','range_add') );
add_filter( 'posts_where' , array('atk','range_where') );
来源:https ://gist.github.com/3904986