3

My categories are basically authors, and I would like to create a function to list them according to their surname. For example I'd like to have something like:

E:

  • Heinz Erhardt
  • Albert Einstein
  • Eminem

The problem is, I also have authors with only one name (like "Eminem") which I would also like to be sorted according to the letter E. The only way I know of to do this in wordpress is with the get_terms function and the name__like.

function getAuthors(){
$args = array(
    'name__like' => 'E',
);
return get_terms('category', $args );
}

this creates the sql query which only lists categories with an "E" in it:

AND t.name LIKE %E%;

I however need something like:

AND t.name NOT LIKE '% %' AND t.name LIKE E% OR t.name LIKE '% E';

I tried to change the code in the get_terms function in the core file where the query is set up (taxonomies.php, line 1809). However I wasn't successfull and I wouldn't like to change something in the core files.

How can I customize the query passed by the name__like? Are there other better ways I can achieve my goal?

--- EDIT ---

I used TheDeadMedic's solution and was able to list categories according to a specific letter by using for example get_terms( 'my_taxonomy', 'surname=E' ); However this surname argument doesn't work if I want to use the get_terms function multiple times on one page (for example in a loop - if I'd like to create A-Z headings and display the according sorted categories below the headings).

Here's the function I'm trying to execute. The problem is that it just keeps listing the categorys for surname=A under every heading.

function getAuthors()
{
$letters = range('A', 'Z'); // create Alphabet array
foreach ($letters as $letter) {
    echo '<h4>' . $letter . '</h4>';
    $args = array(
        'surname' => $letter
    );
    $cats = get_terms('category', $args);

    foreach ($cats as $cat) {
        echo "<ul>";
        echo "<li>" . $cat->name . "</li>";
        echo "</ul>";
    }
  }
}

The name__like argument seems to work in the loop though.

  • 3
    FYI, you should never change any core files, not only because it makes the unicorns angry, but also because if an update is made all of your work goes away. – David Gard Feb 18 '15 at 11:55
5

Use the terms_clauses filter, which passes all the various components of the query (fields, join, where, orderby, order & limits), and implement your own "search" argument:

function wpse_178511_get_terms_fields( $clauses, $taxonomies, $args ) {
    if ( ! empty( $args['surname'] ) ) {
        global $wpdb;

        $surname_like = $wpdb->esc_like( $args['surname'] );

        if ( ! isset( $clauses['where'] ) )
            $clauses['where'] = '1=1';

        $clauses['where'] .= $wpdb->prepare( " AND t.name LIKE %s OR t.name LIKE %s", "$surname_like%", "% $surname_like%" );
    }

    return $clauses;
}

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

Put in use:

 get_terms( 'my_taxonomy', 'surname=E' );
  • looks good, but I somehow can't get it to work. I posted your function exactly like it is in my functions.php. Then I put it in use on my page template and have it echo out the category list through a foreach loop $cats = get_terms( 'category', 'surname=E' );foreach($cats as $cat){... it still prints all the categories though and not the one's with "E"'s on the beginning etc. – ndru Feb 18 '15 at 12:45
  • 1
    Woah, wrong filter! See edit. – TheDeadMedic Feb 18 '15 at 12:54
  • hey this solution works if I want to list all categories with letter 'E' in this specific position but if I want to use it in a loop it somehow doesn't work. plz see my edit on the original question – ndru Feb 21 '15 at 16:05
  • 1
    It's because surname is not a core query argument, so WordPress thinks it's the same query as A and returns a cached result. Add 'name__like' => $letter to $args in addition to surname. – TheDeadMedic Feb 21 '15 at 16:32

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.