Search code examples
phpwordpresscallbackusort

Pass extra parameters to usort callback


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 (v. 5.2.17) 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); 
}

PHP Version: 5.2.17


Solution

  • In PHP, one option for a callback is to pass a two-element array containing an object handle and a method name to call on the object. For example, if $obj was an instance of class MyCallable, and you want to call the method1 method of MyCallable on $obj, then you can pass array($obj, "method1") as a callback.

    One solution using this supported callback type is to define a single-use class that essentially acts like a closure type:

    function sort_by_term_meta( $terms, $meta ) 
    {
        usort($terms, array(new TermMetaCmpClosure($meta), "call"));
    }
    
    function term_meta_cmp( $a, $b, $meta )
    {
        $name_a = get_term_meta($a->term_id, $meta, true);
        $name_b = get_term_meta($b->term_id, $meta, true);
        return strcmp($name_a, $name_b); 
    } 
    
    class TermMetaCmpClosure
    {
        private $meta;
    
        function __construct( $meta ) {
            $this->meta = $meta;
        }
    
        function call( $a, $b ) {
            return term_meta_cmp($a, $b, $this->meta);
        }
    }