Detect changes to Array in PHP

2.4k views Asked by At

I've been using __set magic method with protected properties to monitor changes so that my classes know if they have something to save. Is there any way to monitor an array type property for changes? I understand that normally you access the array via a reference and functions like array_push won't trigger the __set method, they'll use a reference to the array.

What I want is basically this:

class Skill{ public $Player, $Name, $Level;}
class Player {
    protected $Name, /*Other properties*/, $Skills /*Array*/
}

I then do tracking on all of the properties in Player to tell me if the persistence needs updated. (Skill would also have this function, but this shows the basic example). Also, I want to force them to remain synchronized (it's a bidirectional relationship).

Is there any way to do this that allows it to behave like an array (don't want to go through making a class just to synchronize those if I don't have to).

2

There are 2 answers

3
Rob M. On BEST ANSWER

You could extend ArrayObject and proxy append:

class Skills extends ArrayObject
{
    public function append($value)
    {
        // track changes
        parent::append($value);
    }
}
6
Marty On

You could look into something like runkit_function_redifine(), but is it really too cumbersome to make helper methods for what you want? e.g.

class Player
{
    private $skills = array();

    protected function addSkill($skill)
    {
        // Do something.
        //

        $this->skills[] = $skill;
    }
}

Or even a wrapper for an array to make it cleaner:

class FancyArray
{
    private $content = array();
    
    public function add($value)
    {
        // Do something.
        //

        $this->content[] = $value;
    }

    public function remove($value){ /* blah */ }

    public function getContent(){ return $this->content; }
}

class Player
{
    protected $skills;

    public function __construct()
    {
        $this->skills = new FancyArray();
        $this->skills->add("Ninjitsu");
    }
}