Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP:检测变量值何时更改_Php_Variables_Reference_Listener_Magic Methods - Fatal编程技术网

PHP:检测变量值何时更改

PHP:检测变量值何时更改,php,variables,reference,listener,magic-methods,Php,Variables,Reference,Listener,Magic Methods,我想知道是否有一种方法可以将更改侦听器之类的东西添加到变量中。我所说的最简单的例子就是沿着这些思路工作 // Start with a variable $variable = "some value"; // Define a listener function myChangeListener($variable) { // encode with json_encode and send in cookie } // Add my listener to the variabl

我想知道是否有一种方法可以将更改侦听器之类的东西添加到变量中。我所说的最简单的例子就是沿着这些思路工作

// Start with a variable
$variable = "some value";

// Define a listener
function myChangeListener($variable) {
    // encode with json_encode and send in cookie
}

// Add my listener to the variable
addListenerToVariable(&$variable, 'myChangeListener');

// Change the variables value, triggering my listener
$variable = "new value";
现在你可能会问为什么我甚至需要用这种方法,为什么不做一个函数来设置cookie呢。答案是我有一个
&uu get($var)
魔术方法,它返回对多维数组元素的引用,我希望使用类似的方法来检测数组元素或其子元素何时/是否已被编辑,如果已编辑,则发送cookie。希望得到的结果是这样的

$cookies->testArray["test"] = "newValue";
// This would send the cookie 'testArray' with the value '{"test":"newValue"}'
我真的认为这是完全不可能的,如果我是对的,我道歉。但是我昨天刚刚学会了如何正确使用参考资料,所以我想在我完全放弃这个想法之前我应该先问一下

谢谢你给我的回复,无论是我所希望的还是我所期望的

编辑:

为了更加清晰,这里有一个示例类,介绍我试图实现的目标

class MyCookies {
    private $cookies = array();
    private $cookieTag = "MyTag";

    public function __construct() {
        foreach($_COOKIE as $cookie => $value) {
            if(strlen($cookie)>strlen($this->cookieTag."_")&&substr($cookie,0,strlen($this->cookieTag."_"))==$this->cookieTag."_") {
                $cookieVar = substr($cookie,strlen($this->cookieTag."_"));
                $this->cookies[$cookieVar]['value'] = json_decode($value);
            }
        }
    }

    // This works great for $cookies->testArray = array("testKey" => "testValue");
    // but never gets called when you do $cookies->testArray['testKey'] = "testValue";
    public function __set($var, $value) {
        if(isset($value)) {
            $this->cookies[$var]['value'] = $value;
            setcookie($this->cookieTag.'_'.$var,json_encode($value),(isset($this->cookies[$var]['expires'])?$this->cookies[$var]['expires']:(time()+2592000)),'/','');
        } else {
            unset($this->cookies[$var]);
            setcookie($this->cookieTag.'_'.$var,'',(time()-(172800)),'/','');
        }
        return $value;
    }

    // This gets called when you do $cookies->testArray['testKey'] = "testValue";
    public function &__get($var) {
        // I want to add a variable change listener here, that gets triggered
        // when the references value has been changed.

        // addListener(&$this->config[$var]['value'], array(&$this, 'changeListener'));

        return $this->config[$var]['value'];
    }

    /*
    public function changeListener(&$reference) {
        // scan $this->cookies, find the variable that $reference is the reference to (don't know how to do that ether)
        // send cookie
    }
    */

    public function __isset($var) {
        return isset($this->cookies[$var]);
    }

    public function __unset($var) {
        unset($this->cookies[$var]);
        setcookie($this->cookieTag.'_'.$var,'',(time()-(172800)),'/','');
    }

    public function setCookieExpire($var, $value, $expire=null) {
        if(!isset($expire)) {
            $expire = $value;
            $value = null;
        }
        if($expire<time()) $expire = time() + $expire;
        if(isset($value)) $this->cookies[$var]['value'] = $value;
        $this->cookies[$var]['expires'] = $expire;
        setcookie($this->cookieTag.'_'.$var,json_encode((isset($value)?$value:(isset($this->cookies[$var]['value'])?$this->cookies[$var]['value']:''))),$expire,'/','');
    }
}
class mycokies{
private$cookies=array();
私有$cookieTag=“MyTag”;
公共函数构造(){
foreach($\u COOKIE作为$COOKIE=>$value){
如果(strlen($cookie)>strlen($this->cookieTag.”和&substr($cookie,0,strlen($this->cookieTag.”)==$this->cookieTag.){
$cookieVar=substr($cookie,strlen($this->cookieTag.);
$this->cookies[$cookieVar]['value']=json\u decode($value);
}
}
}
//这对$cookies->testArray=array(“testKey”=>“testValue”)非常有效;
//但是当您执行$cookies->testArray['testKey']=“testValue”时,永远不会被调用;
公共函数集($var,$value){
if(isset(价值)){
$this->cookies[$var]['value']=$value;
setcookie($this->cookieTag.''.'.''.$var,json_encode($value),(isset($this->cookies[$var]['expires'])?$this->cookies[$var]['expires']:(time()+2592000)),'/','';
}否则{
未设置($this->cookies[$var]);
setcookie($this->cookieTag.''.'var',(time()-(172800)),'/','';
}
返回$value;
}
//当您执行$cookies->testArray['testKey']=“testValue”操作时,会调用此函数;
公共函数和获取($var){
//我想在这里添加一个变量更改侦听器,它会被触发
//当引用值已更改时。
//addListener(&$this->config[$var]['value'],数组(&$this,'changeListener');
返回$this->config[$var]['value'];
}
/*
公共函数changeListener(&$reference){
//扫描$this->cookies,找到$reference所引用的变量(不知道如何做)
//发送cookie
}
*/
公共功能集($var){
返回isset($this->cookies[$var]);
}
公共功能未设置($var){
未设置($this->cookies[$var]);
setcookie($this->cookieTag.''.'var',(time()-(172800)),'/','';
}
公共函数setCookieExpire($var,$value,$expire=null){
如果(!isset($expire)){
$expire=$value;
$value=null;
}
如果($expirecookies[$var]['value']=$value;
$this->cookies[$var]['expires']=$expire;
setcookie($this->cookieTag.'''.''.'.'.''.$var,json_编码((isset($value)?$value:(isset($this->cookies[$var]['value']])?$this->cookies[$var]['value']:''),$expire,'/','';
}
}

至于为什么我不想有一个更新功能,这实际上只是个人喜好。这将被用于一个其他人可以扩展的框架中,我认为让他们能够将cookie作为单行代码中的变量来对待会让人感觉更流畅。

我认为你的想法有一些错误,因为它们只是在php中,变量可以改变它的值是如果你改变它。因此,当你改变你的变量时,运行你的代码

如果您需要一种通用的方法来实现这一点,我建议您将数组或其值封装到一个类中。但是,没有理由不在每次值更改后运行sendCookie()


我认为更改侦听器适用于多线程编程。

完全不更改变量怎么样

只通过一个函数(或类方法)访问变量如何?这个函数(或类方法)可以处理您想要执行的任何“侦听”任务

为什么必须这样做:
$variable=5;

何时可以执行:
setMyVariable(5)


若您想在数组或其他任何东西中实现自己的事件处理程序/触发器,那个么您可以使用类包装器

正如您所注意到的,对于一个变量
\uu get()
\uu set()
来说,魔术方法就足够了。 对于数组,有一个更好的处理程序:。它允许使用类方法和通用数组语义(如某些其他语言中的集合)模拟数组操作



我假设,您可以使用数组引用参数修改此代码中的构造函数,以便能够传递超全局数组,如
$\u COOKIE
。另一种方法是直接在类中用
$\u COOKIE
替换
$this->array
。此外,还有一种方法可以将可调用项替换为。

我认为这在类中是不可能的php.For自定义类实现SplObserver接口可能是一个选项,但您必须在进行更改时通知。我不明白您的magic get方法与此有什么关系。此外,您的第二个代码示例似乎与第一个代码示例没有太多关系。我认为更好的代码示例会为我澄清一些问题。我将st抛出一些东西,希望它朝着正确的方向发展:_set()?!这样你也可以看到变量何时被更改。但是一旦我真正知道你想要什么,我就能更好地帮助你。PHP确实有一些侦听器功能。@MichaSchwab我已经用一个示例类更新了我的问题。“你的
function setMyVariable($new_value) {
  $variable = $new_value;
  // do other stuff

}
<?php
header('Content-Type: text/plain');

// ArrayAccess for Array events
class TriggerableArray implements ArrayAccess {
    protected $array;      // container for elements
    protected $triggers;   // callables to actions

    public function __construct(){
        $this->array    = array();

        // predefined actions, which are availible for this class:
        $this->triggers = array(
            'get'    => null,     // when get element value
            'set'    => null,     // when set existing element's value
            'add'    => null,     // when add new element
            'exists' => null,     // when check element with isset()
            'unset'  => null      // when remove element with unset()
        );
    }

    public function __destruct(){
        unset($this->array, $this->triggers);
    }

    public function offsetGet($offset){
        $result = isset($this->array[$offset]) ? $this->array[$offset] : null;

        // fire "get" trigger
        $this->trigger('get', $offset, $result);

        return $result;
    }

    public function offsetSet($offset, $value){
        // if no offset provided
        if(is_null($offset)){
            // fire "add" trigger
            $this->trigger('add', $offset, $value);

            // add element
            $this->array[] = $value;
        } else {
            // if offset exists, then it is changing, else it is new offset
            $trigger = isset($this->array[$offset]) ? 'set' : 'add';

            // fire trigger ("set" or "add")
            $this->trigger($trigger, $offset, $value);

            // add or change element
            $this->array[$offset] = $value;
        }
    }

    public function offsetExists($offset){
        // fire "exists" trigger
        $this->trigger('exists', $offset);

        // return value
        return isset($this->array[$offset]);
    }

    public function offsetUnset($offset){
        // fire "unset" trigger
        $this->trigger('unset', $offset);

        // unset element
        unset($this->array[$offset]);
    }

    public function addTrigger($trigger, $handler){
        // if action is not availible and not proper handler provided then quit
        if(!(array_key_exists($trigger, $this->triggers) && is_callable($handler)))return false;

        // assign new trigger
        $this->triggers[$trigger] = $handler;

        return true;
    }

    public function removeTrigger($trigger){
        // if wrong trigger name provided then quit
        if(!array_key_exists($trigger, $this->triggers))return false;

        // remove trigger
        $this->triggers[$trigger] = null;

        return true;
    }

    // call trigger method:
    // first arg  - trigger name
    // other args - trigger arguments
    protected function trigger(){
        // if no args supplied then quit
        if(!func_num_args())return false;

        // here is supplied args
        $arguments  = func_get_args();

        // extract trigger name
        $trigger    = array_shift($arguments);

        // if trigger handler was assigned then fire it or quit
        return is_callable($this->triggers[$trigger]) ? call_user_func_array($this->triggers[$trigger], $arguments) : false;
    }
}

function check_trigger(){
    print_r(func_get_args());
    print_r(PHP_EOL);
}

function check_add(){
    print_r('"add" trigger'. PHP_EOL);
    call_user_func_array('check_trigger', func_get_args());
}

function check_get(){
    print_r('"get" trigger'. PHP_EOL);
    call_user_func_array('check_trigger', func_get_args());
}

function check_set(){
    print_r('"set" trigger'. PHP_EOL);
    call_user_func_array('check_trigger', func_get_args());
}

function check_exists(){
    print_r('"exists" trigger'. PHP_EOL);
    call_user_func_array('check_trigger', func_get_args());
}

function check_unset(){
    print_r('"unset" trigger'. PHP_EOL);
    call_user_func_array('check_trigger', func_get_args());
}

$victim = new TriggerableArray();

$victim->addTrigger('get', 'check_get');
$victim->addTrigger('set', 'check_set');
$victim->addTrigger('add', 'check_add');
$victim->addTrigger('exists', 'check_exists');
$victim->addTrigger('unset', 'check_unset');

$victim['check'] = 'a';
$victim['check'] = 'b';

$result = $victim['check'];

isset($victim['check']);
unset($victim['check']);

var_dump($result);
?>
"add" trigger
Array
(
    [0] => check
    [1] => a
)

"set" trigger
Array
(
    [0] => check
    [1] => b
)

"get" trigger
Array
(
    [0] => check
    [1] => b
)

"exists" trigger
Array
(
    [0] => check
)

"unset" trigger
Array
(
    [0] => check
)

string(1) "b"