使用“name_like”按首字母列出自定义分类术语即使在使用“term_clauses”挂钩过滤查询后也不起作用
Listing custom taxonomy terms by first letter using “name_like" does not work even after filtering query using “term_clauses” hook
我有一个书籍作者的自定义分类法。我需要用字母表中的字母创建一个索引,当用户单击一个字母时,索引下方会出现一个列表,其中包含姓氏以该字母开头的所有书籍作者。我让一切都很好地工作,除了它会列出在术语中的任何地方找到字母的所有术语,而不仅仅是第一个字母:
<?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', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'þ'=>'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>
我研究了很多,发现“name_like”的行为在较新版本的 Wordpress 中发生了变化。在这个 post 的帮助下,我使用 term_clauses 挂钩来过滤我的 functions.php 文件中的查询:
function llps_filter_term_clauses( $clauses ) {
remove_filter('term_clauses','llps_filter_term_clauses');
$pattern = '|(name LIKE )\'%(.+%)\'|';
$clauses['where'] = preg_replace($pattern,' \'\'',$clauses['where']);
return $clauses;
}
add_filter('terms_clauses','llps_filter_term_clauses');
它成功了——我确信它成功了……直到我下次登录该项目。它不再工作了,我一辈子都弄不明白为什么!
我遇到了同样的问题。可能在最新的 WP 版本中发生了一些变化。我在 4.9.1
中遇到了问题
这是我修复它的方式,我改变了这个:
$pattern = '|(name LIKE )\'%(.+%)\'|';
进入这个:
$pattern = '|(name LIKE )\'{.*?}(.+{.*?})\'|';
如果你想知道我为什么这样做,我建议临时打印出 preg_replace 前后的 $clauses。我的意思是在你的代码中是这样的:
function llps_filter_term_clauses( $clauses ) {
echo '<pre>';print_r($clauses);echo "\n";
remove_filter('term_clauses','llps_filter_term_clauses');
$pattern = '|(name LIKE )\'%(.+%)\'|';
$clauses['where'] = preg_replace($pattern,' \'\'',$clauses['where']);
print_r($clauses);die();
return $clauses;
}
您应该看到 sql LIKE 运算符中典型的“%”被 WP 转换为类似:
{be8aacdf46dd49d9036fd16c13613bf3036378f188b35353535353416ae7d88884444d20} [= 27 = 27 =]您的信
即{} 中的一个字符串,这就是我更改过滤器中的正则表达式的原因。希望这有帮助。
实际上,您可以创建自定义参数而不是替换 where 子句
例如:
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;
}
并用
之类的名称来调用它
$terms = get_terms( array(
'taxonomy' => $taxonomy,
'__first_letter' => 'a', // desired 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', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'þ'=>'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>
我研究了很多,发现“name_like”的行为在较新版本的 Wordpress 中发生了变化。在这个 post 的帮助下,我使用 term_clauses 挂钩来过滤我的 functions.php 文件中的查询:
function llps_filter_term_clauses( $clauses ) {
remove_filter('term_clauses','llps_filter_term_clauses');
$pattern = '|(name LIKE )\'%(.+%)\'|';
$clauses['where'] = preg_replace($pattern,' \'\'',$clauses['where']);
return $clauses;
}
add_filter('terms_clauses','llps_filter_term_clauses');
它成功了——我确信它成功了……直到我下次登录该项目。它不再工作了,我一辈子都弄不明白为什么!
我遇到了同样的问题。可能在最新的 WP 版本中发生了一些变化。我在 4.9.1
中遇到了问题这是我修复它的方式,我改变了这个:
$pattern = '|(name LIKE )\'%(.+%)\'|';
进入这个:
$pattern = '|(name LIKE )\'{.*?}(.+{.*?})\'|';
如果你想知道我为什么这样做,我建议临时打印出 preg_replace 前后的 $clauses。我的意思是在你的代码中是这样的:
function llps_filter_term_clauses( $clauses ) {
echo '<pre>';print_r($clauses);echo "\n";
remove_filter('term_clauses','llps_filter_term_clauses');
$pattern = '|(name LIKE )\'%(.+%)\'|';
$clauses['where'] = preg_replace($pattern,' \'\'',$clauses['where']);
print_r($clauses);die();
return $clauses;
}
您应该看到 sql LIKE 运算符中典型的“%”被 WP 转换为类似:
{be8aacdf46dd49d9036fd16c13613bf3036378f188b35353535353416ae7d88884444d20} [= 27 = 27 =]您的信
即{} 中的一个字符串,这就是我更改过滤器中的正则表达式的原因。希望这有帮助。
实际上,您可以创建自定义参数而不是替换 where 子句
例如:
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;
}
并用
之类的名称来调用它$terms = get_terms( array(
'taxonomy' => $taxonomy,
'__first_letter' => 'a', // desired first letter
) );