Pass extra parameters to usort callback

djb picture djb · Nov 22, 2011 · Viewed 30.4k times · Source

I have the following functions. WordPress functions, but this is really a PHP question. They sort my $term objects according to the artist_lastname property in each object's metadata.

I want to pass a string into $meta in the first function. This would let me reuse this code as I could apply it to various metadata properties.

But I don't understand how I can pass extra parameters to the usort callback. I tried to make a JS style anonymous function but the PHP version on the server is too old and threw a syntax error.

Any help - or a shove towards the right corner of the manual - gratefully appreciated. Thanks!

function sort_by_term_meta($terms, $meta) 
{
  usort($terms,"term_meta_cmp");
}

function term_meta_cmp( $a, $b ) 
{
    $name_a = get_term_meta($a->term_id, 'artist_lastname', true);
    $name_b = get_term_meta($b->term_id, 'artist_lastname', true);
    return strcmp($name_a, $name_b); 
} 

Answer

Bas picture Bas · Mar 24, 2014

I think this question deserves an update. I know the original question was for PHP version 5.2, but I came here looking for a solution and found one for newer versions of PHP and thought this might be useful for other people as well.

For PHP 5.3 and up, you can use the 'use' keyword to introduce local variables into the local scope of an anonymous function. So the following should work:

function sort_by_term_meta(&$terms, $meta) {
    usort($terms, function($a, $b) use ($meta) {
        $name_a = get_term_meta($a->term_id, 'artist_lastname', true);
        $name_b = get_term_meta($b->term_id, 'artist_lastname', true);
        return strcmp($name_a, $name_b);  
    });
}

Some more general code

If you want to sort an array just once and need an extra argument you can use an anonymous function like this:

usort($arrayToSort, function($a, $b) use ($myExtraArgument) {
    //$myExtraArgument is available in this scope
    //perform sorting, return -1, 0, 1
    return strcmp($a, $b);
});

If you need a reusable function to sort an array which needs an extra argument, you can always wrap the anonymous function, like for the original question:

function mySortFunction(&$arrayToSort, $myExtraArgument1, $myExtraArgument2) {
    usort($arrayToSort, function($a, $b) use ($myExtraArgument1, $myExtraArgument2) {
        //$myExtraArgument1 and 2 are available in this scope
        //perform sorting, return -1, 0, 1
        return strcmp($a, $b);
    });
}