1

I had a template that relied on

$terms = get_terms( "ingredient", array( 'name__like' => $letter ) );

to return all posts where the custom taxonomy ingredient begins with $letter.

The behaviour of name__like was changed in WP 3.7 to a text search instead of beginning.

What function can I use to achieve the results I had before? Do I need a custom query?

8

You will need to filter the query, which you can do with the terms_clauses hook. This is very similar to G-M's solution but does not require a prefix on your search string.

function old_style_name_like_wpse_123298($clauses) {
  remove_filter('term_clauses','old_style_name_like_wpse_123298');
  $pattern = '|(name LIKE )\'%(.+%)\'|';
  $clauses['where'] = preg_replace($pattern,'$1 \'$2\'',$clauses['where']);
  return $clauses;
}
add_filter('terms_clauses','old_style_name_like_wpse_123298');
// $letter = 'str'; // test
$terms = get_terms( "ingredient", array( 'name__like' => $letter ) )
| improve this answer | |
  • Good one (+1), however once it will affect any get_terms calls that include 'name__like' or 'search' argument, you should include in the pattern some (all?) not alphanumeric chars, once they are legal taxonomy name args... (LIKE clause is applyed to term name, not to term slug). Probably $pattern = '|(name LIKE )\'%(.+%)\'|'; can be a good choice because query is already sanitized by WP. – gmazzap Nov 14 '13 at 20:52
  • @G-M : the filter removes itself so it should only effect the next use of get_terms and, yes, I am sure the regex could be tweaked :) – s_ha_dum Nov 14 '13 at 21:47
  • E.g.: add_filter('terms_clauses','old_style_name_like_wpse_123298'); get_terms( "category", array( 'name__like' => '¿' ) ); to retrieve categories starting with '¿' will not work as expected.. in spanish-speaking countries people use WordPress too ;) – gmazzap Nov 14 '13 at 22:09
  • @G-M : edited per your suggestion – s_ha_dum Nov 15 '13 at 1:34
  • I'd like to but I can't +1 again :) – gmazzap Nov 15 '13 at 1:44
1

This is a trick.

Prepend to the letter you want to search a strange string:

$letter = '§§§' . 'a'; // strange string plus the letter you want to search

Then apply a filter to terms_clauses hook:

add_filter('terms_clauses', 'replace_name__like_for_ingredients', 10, 3);

$terms = get_terms( "ingredient", array( 'name__like' => $letter ) );

Finally use that function to remove the % preceding the strange string and the strange string itself:

function replace_name__like_for_ingredient( $pieces, $taxonomies, $args ) {
  if ( in_array('ingredient', $taxonomies) ) {
    // replace the perc sign plus strange string with empty string so
    // LIKE '%§§§a%' become LIKE 'a%'
    $pieces['where'] = str_replace("%§§§", '', $pieces['where']);
  }
  return $pieces;
}

Untested.

| improve this answer | |
0

I can't comment on the previous answers, so I'll add this note here in case anyone else faces this problem too: The above wasn't working for me, so I replaced:

$pattern = '|(name LIKE )\'%(.+%)\'|';

with

$pattern = '|(name LIKE )\'{.*?}(.+{.*?})\'|';

as suggested here: https://stackoverflow.com/questions/47840519/listing-custom-taxonomy-terms-by-first-letter-using-name-like-does-not-work-ev

| improve this answer | |
0

Based on gmazaap's reply, I got this:

$terms_array = [
    'taxonomy' => 'pa_myattr',
    'name__like' => '§§§' . 'A'
];
$terms = get_terms($terms_array);

add_filter('terms_clauses', 'replace_name__like_for_product_attribute', 10, 3);
function replace_name__like_for_product_attribute($pieces, $taxonomies, $args)
{
  if (in_array('pa_myattr', $taxonomies)) {
    // replace the perc sign plus strange string with empty string so
    // LIKE '{abc..}§§§a{abc...}' become LIKE 'A%'
    $pieces['where'] = preg_replace('/(.* LIKE ).*§§§([A-Z])(.*)/', '$1\'$2$3', $pieces['where']);
  }
  return $pieces;
}

Tested with WordPress 5.2.2

Had to modify the regular str_replace with a preg_match because now WordPress seems to add something like a hash to protect SQL injections. Since this string seems to be random between queries the only solution is to use regex.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.