PHP: Detecting when a variables value has been changed -
i wondering if there way add change listener variable. simplest example of mean work along these lines;
// start variable $variable = "some value"; // define listener function mychangelistener($variable) { // encode json_encode , send in cookie } // add listener variable addlistenertovariable(&$variable, 'mychangelistener'); // change variables value, triggering listener $variable = "new value"; now you're asking why in world need bother approach, why not make function set cookie. answer i've got &__get($var) magic method returns reference multi-dimensional array element, , hoping use detect when/if array element or 1 of children has been edited, send cookie if has. hoped result work this;
$cookies->testarray["test"] = "newvalue"; // send cookie 'testarray' value '{"test":"newvalue"}' i expect impossible, , apologize if i'm correct. learned how use references correctly yesterday, thought i'd ask before write off idea.
thanks responses get, hoping or expected.
edit:
for added clarity, here's example class i'm trying accomplish;
class mycookies { private $cookies = array(); private $cookietag = "mytag"; public function __construct() { foreach($_cookie $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); } } } // works great $cookies->testarray = array("testkey" => "testvalue"); // never gets called when $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; } // gets called when $cookies->testarray['testkey'] = "testvalue"; public function &__get($var) { // want add variable change listener here, gets triggered // when 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 variable $reference reference (don't know how 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,'/',''); } } as why don't want have update function, it's personal preference. going used in framework other people can expand upon, , think having them able treat cookies variables in single lines of code feels slicker.
if want implement own event handlers / triggers in array or else, might use class wrapper.
for one variable __get() , __set() magic methods enough, noticed. array there better handler: arrayaccess. allows emulate array actions class methods , common array semantics (like collections in other languages).
<?php header('content-type: text/plain'); // arrayaccess array events class triggerablearray implements arrayaccess { protected $array; // container elements protected $triggers; // callables actions public function __construct(){ $this->array = array(); // predefined actions, availible class: $this->triggers = array( 'get' => null, // when element value 'set' => null, // when set existing element's value 'add' => null, // when add new element 'exists' => null, // when check element isset() 'unset' => null // when remove element 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, changing, else 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 not availible , not proper handler provided 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 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 quit if(!func_num_args())return false; // here supplied args $arguments = func_get_args(); // extract trigger name $trigger = array_shift($arguments); // if trigger handler assigned fire 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); ?> shows:
"add" trigger array ( [0] => check [1] => ) "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" i assume, might modify constructor in code array reference argument able pass there superglobal array, $_cookie. way replace $this->array $_cookie directly within class. also, there way replace callables anonymous functions.
Comments
Post a Comment