DrDamnit
DrDamnit

Reputation: 4826

How to use usort on an object with an array of arrays

Simply put: I need to sort an array of objects based on a specific value of a specific array element inside a class property.

This would be great, if it worked: Psuedo code that illustrates what I need

In this picture, the code illustrates what I want: I want to be able to tell usort to look in a specific array element and find the priority key, and sort based on that integer value.

So, for a given hook (hook-foo), I would need the comparison to be done on:

 $plugin->hooks['hook-foo']['priority']

For another hook (hook-bar), for which the same plugin might act upon, I need the sort to look at:

 $plugin->hooks['hook-bar']['priority']

if usort supported me sending an arbitrary argument to it, this would be solved. But, the code pictured below was written to illustrate my point and then tested because "maybe it will work". It didn't.

How do I rearrange this to get the sort I need?

(Note: Plugin::hooks is an array of arrays and represents all the metadata required to execute a plugin on a given hook. So, it may contain 'hook-foo' and 'hook-bar', which do not execute at the same time. It may also contain one or the other, or... neither.)

Edit: Here are the example structures, which may help illustrate my point. This shows 2 of 14 plugins loaded.

Example of two plugins

You can see that each plugin responds to multiple different hooks.

So, if I wanted to control the order for a given hook, I should only have to change the priority of that hook.

For example, here: you can see the cli-init hook fires a method of the class declareMySelf, which simply says: "Plugin XYZ loaded" in the command line interface. Both of the priorities are 50, so it will display them in whatever order the system finds the plugins.

But, if I wanted to display "PHP Mailer loaded" BEFORE I display "Config / Settings management loaded", all I should have to do is drop the PHP Mailer plugin priority to 40.

Upvotes: 0

Views: 77

Answers (1)

Henrique Barcelos
Henrique Barcelos

Reputation: 7900

You should probably have a $hookSearchKey property within your class and set it with a setHookSearchKey() method when needed:

class Whatever {
    // ...
    private $hookSearchKey

    public function setHookSearchKey($key) {
        $this->hookSearchKey = $key;
    }

    //... this is your method of sorting:
    public function fooSort(...) {
        $this->setHookSearchKey('hook-foo');
        usort(...); // do your thing
    }

    //... this is your method of sorting:
    public function barSort(...) {
        $this->setHookSearchKey('hook-bar');
        usort(...); // do your thing
    }

    //...

    public function sortByHookPriority(...) {
        if($a[$this->hookSearchKey] == $b[$this->hookSearchKey]) return 0;

        // ...
    }
}

Would this work for you?

Upvotes: 1

Related Questions