दिलचस्प सवाल! मैंने खंडों के 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
)।
पृष्ठ पर अंक लगाना जोड़ना पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है :-)