2

Is PHP exists a function that detect the change of variable? That is something like this:

//called when $a is changed.
function variableChanged($value) {
    echo "value changed to " . $value;
}

$a = 1;
//attach the variable to the method.
$a.attachTo("variableChanged");
$a = 2;
$a = 3;

//expected output:
//value changed to 2
//value changed to 3

I know that it is easy to achieve if I use the "setter" method. But since I am working on some existing codes, I am not able to modify them. Can somebody tell me how to achieve my purpose? Thanks.

10
  • 3
    The short answer is it's not possible (except with a debugger). What is your use case, why do you need this? Commented Jul 9, 2013 at 8:09
  • 1
    PHP execution is linear not event based so I don't think you can do that. Commented Jul 9, 2013 at 8:10
  • This is a very peculiar thing to need, in most cases. Commented Jul 9, 2013 at 8:10
  • 2
    This looks like an instance of the XY problem to me. Commented Jul 9, 2013 at 8:21
  • 1
    @DanFromGermany sure, but what's the point? What the OP seems to need is a debugger. Commented Jul 9, 2013 at 8:44

4 Answers 4

5

know that it is easy to achieve if I use the "setter" method. But since I am working on some existing codes, I am not able to modify them.

I assume that you can change some code, but not the object / class you are working with. If you cannot change any code at all this question would be useless.

What you can do is make your own class, extending the class you are working with, and adding your setter there. For all purposes you can not-override the parent setting, except for a magic setter on whatever you need to track. Track changes and then call the parent functions, so no changes in any other internal workings will be in effect.

Sign up to request clarification or add additional context in comments.

Comments

3

This could only be achieved by wrapping your variable within a class, and implementing a onchange yourself.

ie.

class MyVarContainer {
    var $internalVar = array();

    function __get($name) {
        return !empty($this->internalVar[$name]) $this->internalVar[$name] ? FALSE;
    }

    function __set($name, $value) {
       $oldval = $this->$name;
       $this->internalVar[$name] = $value;

       if($oldval !== FALSE) {
          onUpdated($name, $oldval, $value);
       } else {
          onCreated($name, $value);
       }
    }

    function onCreated($name, $value) {

    }

    function onUpdated($name, $oldvalue, $newvalue) {

    }
}

Comments

1

You could revised your code as simple like this just to produce that expected output you want.

function variableChanged($value) {
    return "value changed to " . $value;
    }

    $a = 1;

    echo $a = variableChanged(2);
    echo '<br/>';
    echo $a = variablechanged(3);

=================
//output
value changed to 2
value changed to 3

or using a class like this....

class VariableHandler{

        private $Variable;


        function setVariable($initialValue = NULL){
            $this->Variable = $initialValue;
            return $initialValue;
        }

        function changeValue($newValue = NULL){
            $this->Variable = $newValue;
            return "value has change to ". $newValue;
        }


    }

    $var = new VariableHandler;

    echo $a = $var->setVariable(1);
    echo '<br/>';
    echo $var->changeValue(2);
    echo '<br/>';
    echo $var->changeValue(3);

 =================
    //output
    value changed to 2
    value changed to 3

Comments

1

Besides using a debugger:

The SplObserver interface is used alongside SplSubject to implement the Observer Design Pattern. http://www.php.net/manual/en/class.splobserver.php

Or the magic methods __get() and __set(): Encapsulating the variable into a class, you could implement a event handler yourself and register the change of a variable. Also you could attach callbacks like here:

<?php
header("content-type: text/plain");

class WatchVar {
    private $data = array();
    private $org = array();
    private $callbacks = array();

    public function __set($name, $value) {
        if (!array_key_exists($name, $this->data)) {
            $this->org[$name] = $value;
        } else {
            //variable gets changed again!
            $this->triggerChangedEvent($name, $value);
        }
        $this->data[$name] = $value;
    }

    public function &__get($name) {
        if (array_key_exists($name, $this->data)) {
            if ($this->data[$name] != $this->org[$name]) {
                //variable has changed, return original
                //return $this->org[$name];
                //or return new state:
                return $this->data[$name];
            } else {
                //variable has not changed
                return $this->data[$name];
            }
        }
    }

    public function addCallback($name, $lambdaFunc) {
        $this->callbacks[$name] = $lambdaFunc;
    }

    protected function triggerChangedEvent($name, $value) {
        //$this->data[$name] has been changed!
        //callback call like:
        call_user_func($this->callbacks[$name], $value);
    }
}


$test = new WatchVar;
$test->addCallback('xxx', function($newValue) { echo "xxx has changed to {$newValue}\n"; });
$test->xxx = "aaa";

echo $test->xxx . "\n";
//output: aaa

$test->xxx = "bbb";
//output: xxx has changed to bbb

echo $test->xxx . "\n";
//output bbb

function messyFunction(&$var) {
    $var = "test";
}

messyFunction($test->xxx);
//output:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.