Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
179 views
in Technique[技术] by (71.8m points)

php - Listing custom taxonomy terms by first letter using “name_like" does not work even after filtering query using “term_clauses” hook

I have a custom taxonomy for book authors. I need to create an index with the letters of the alphabet and when the user clicks on a letter a list appears underneath the index with all the book author whose last name starts with that letter. I got everything to work nicely except that it would list all terms where the letter was found anywhere within the term, not only the first letter:

<?php global $product;

$name_like = isset($_GET['character']) ? $_GET['character'] : '';
$letters = range('A', 'Z');
$term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); 
   $slug = $term->slug;
?>

<div id="content-small">
    <div class="list-terms">

        <div class="alphanav">
            <?php foreach ($letters as $letter): ?>
                <?php if (strtoupper($name_like) == strtoupper($letter)):?>
                    <a class='selected' href="<?php bloginfo('url'); ?>/auteurs/<?php echo $slug ?>?character=<?php echo strtoupper($letter)?>"><?php echo strtoupper($letter)?></a>
                <?php else: ?>
                    <a href="<?php bloginfo('url'); ?>/auteurs/<?php echo $slug ?>?character=<?php echo strtoupper($letter)?>"><?php echo strtoupper($letter)?></a>
                <?php endif;?>
            <?php endforeach;?>
            <a class="selected set-height" href="<?php bloginfo('url'); ?>/auteurs/<?php echo $slug ?>?character=#">#</a>
        </div>
<?php

$taxonomy = 'auteurs';
$queried_term = get_query_var($taxonomy);
$args = array(
'name__like' => $name_like,
   'orderby'   => 'name',
   'order' => 'ASC',
   );

$terms = get_terms($taxonomy, $args, 'slug='.$queried_term);

if ($terms) {
   $count = count($terms);
            $i=0;
            $term_list = '<div class="tab-auteur">
   <input id="tab-one-auteur" type="checkbox" name="tabs-auteur">
                          <label for="tab-one-auteur">La Liste</label>
                          <ul class="bio-list tab-content-auteur">';
            //echo '<h2 class="term-letter">'. strtoupper($name_like) . '</h2>';

 foreach($terms as $term) {
   $names = $term->name;
   $unwanted_array = array(    '?'=>'S', '?'=>'s', '?'=>'Z', '?'=>'z', 'à'=>'A', 'á'=>'A', '?'=>'A', '?'=>'A', '?'=>'A', '?'=>'A', '?'=>'A', '?'=>'C', 'è'=>'E', 'é'=>'E',
                        'ê'=>'E', '?'=>'E', 'ì'=>'I', 'í'=>'I', '?'=>'I', '?'=>'I', '?'=>'N', 'ò'=>'O', 'ó'=>'O', '?'=>'O', '?'=>'O', '?'=>'O', '?'=>'O', 'ù'=>'U',
                        'ú'=>'U', '?'=>'U', 'ü'=>'U', 'Y'=>'Y', 'T'=>'B', '?'=>'Ss', 'à'=>'a', 'á'=>'a', 'a'=>'a', '?'=>'a', '?'=>'a', '?'=>'a', '?'=>'a', '?'=>'c',
                        'è'=>'e', 'é'=>'e', 'ê'=>'e', '?'=>'e', 'ì'=>'i', 'í'=>'i', '?'=>'i', '?'=>'i', 'e'=>'o', '?'=>'n', 'ò'=>'o', 'ó'=>'o', '?'=>'o', '?'=>'o',
                        '?'=>'o', '?'=>'o', 'ù'=>'u', 'ú'=>'u', '?'=>'u', 'y'=>'y', 't'=>'b', '?'=>'y' );
$firstname = substr($names, strpos($names, ",") + 1); 
$arr = explode(",", $names, 2);
$lastname = $arr[0]; 
$lastname = strtr( $lastname, $unwanted_array );  
$lastname = strtoupper( $lastname );
$comma   = ',';
$whichname = strpos($names, $comma);

if ($whichname === false) {
$full = strtoupper( $names );
} else {
$full = $lastname . ', ' . $firstname;
}

$i++;
                $term_list .= '<li><a href="'.get_term_link($term->slug, 
$taxonomy).'?character='. $name_like .'">' . $full . '</a></li>';
            if ($count != $i) {
                    $term_list .= '';
                }
            else {
                    $term_list .= '</ul></div>';
                }
            }
            echo $term_list;

 }
else {
    echo '<ul class="bio-list">PAS DE AUTEURS</ul>';
 }
 ?>
 </div> 

I researched a lot and found the behaviour of “name_like” changed in the newer versions of Wordpress. With the help of this post I used the term_clauses hook to filter the query in my functions.php file:

function llps_filter_term_clauses( $clauses ) {
  remove_filter('term_clauses','llps_filter_term_clauses');
  $pattern = '|(name LIKE )'%(.+%)'|';
  $clauses['where'] = preg_replace($pattern,'$1 '$2'',$clauses['where']);
  return $clauses;
}

add_filter('terms_clauses','llps_filter_term_clauses');

and it worked - I’m sure it did… until the next time I logged onto the project. It’s not working anymore and I can’t for the life of me figure out why!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Actually, you can create a custom parameter instead of replacing the where clause

for example :

add_filter( 'terms_clauses', 'terms_clauses_47840519', 10, 3 );
function terms_clauses_47840519( $clauses, $taxonomies, $args ){
    global $wpdb;

    if( !isset( $args['__first_letter'] ) ){
        return $clauses;
    }

    $clauses['where'] .= ' AND ' . $wpdb->prepare( "t.name LIKE %s", $wpdb->esc_like( $args['__first_letter'] ) . '%' );

    return $clauses;

}

and call it with something like

$terms = get_terms( array(
    'taxonomy' => $taxonomy,
    '__first_letter' => 'a', // desired first letter
) );

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...