PHP Usort in a parent static class with callback in the calling static class

1.4k Views Asked by At

I have a "static class" used as a singleton (because there's never a need to have multiple instances), and other classes that extend it and are used in the same way.

At some point in the processing, the extended class will call parent::doThis(), with doThis ultimately doing a usort.

The callback of the usort should be in the calling class, as each will handle sorting differently. Can something like "class::method()" be the string for a usort callback, and if so, is there a way for the parent class to know which class called it without me passing that as an argument, so that it can name the calling class's callback for the usort?

class parentClass {
  protected static function doThis($data) {
    // do stuff, then
    usort($data, "myCallingClass::cmp()"
  }
}

based on some means of the parent determining what myCallingClass is, or does it need to be

class parentClass {
  protected static function doThis($data, $calling_class) {
    // do stuff, then
    usort($data, $calling_class . "::cmp()"
  }
}
3

There are 3 best solutions below

9
On BEST ANSWER

I think you should be able to do this with Late Static Bindings:

usort($data, function($a, $b) {return(static::cmp($a, $b));});
0
On

you can add static function name() { return "myCallingClass"; } to each class with it's own name. Then all you need is to call

usort($data, static::name() . "::cmp()");

static modifer assures you that method will be called from inheriting class if it has one.

0
On

A simple solution is to use a well-known callback name in combination with get_called_class:

class Numbers
{
    static function sort() {
        $things = [1,2,3,4,5];
        usort($things, [get_called_class(), 'cmp']);
        print join(' ', $things);
    }
}

class Mod2 extends Numbers {
    static function cmp($a, $b) {
        return $a % 2 - $b % 2;
    }
}

Mod2::sort(); // 4 2 5 3 1

A not-so-simple, but correct solution is to forget all this "static classes" and "singletons" stuff and use objects the way they are intended to be used:

class Numbers
{
    function sort() {
        $things = [1,2,3,4,5];
        usort($things, [$this, 'cmp']);
        print join(' ', $things);
    }
}

class Mod2 extends Numbers {
    function cmp($a, $b) {
        return $a % 2 - $b % 2;
    }
}

(new Mod2)->sort(); // 4 2 5 3 1