I was wondering if there is a way to add something like a change listener to a variable. The simplest example of what I mean would work something along these lines;
// 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";
Now you're probably asking why in the world I would even need to bother with this approach, why not just make a function to set the cookie. The answer is I've got a &__get($var)
magic method that returns a reference to a multi-dimensional array element, and I am hoping to use something like this to detect when/if the array element or one of its children has been edited, then send a cookie if it has. The hoped for result would work something like this;
$cookies->testArray["test"] = "newValue";
// This would send the cookie 'testArray' with the value '{"test":"newValue"}'
I honestly expect this to be completely impossible, and I apologize if I'm correct. But I just learned how to use references correctly yesterday, so I thought I'd ask before I completely write off the idea.
Thanks for any responses I get, be they what I was hoping for or what I expected.
EDIT:
For added clarity, here's an example class for what I'm trying to accomplish;
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,'/','');
}
}
As for why I don't want to have an update function, it's really just personal preference. This is going to be used in a framework that other people can expand upon, and I think having them be able to treat the cookies as just variables in single lines of code feels slicker.
I think you have some error in your thinking because they only way a variable can change its value in php is if you change it. Therefore, when you change your variable, run your code.
If you need a generic way of doing this, I would suggest encapsulating either the array or its values into a class. But there really is no good reason you can't just run sendCookie() after each value change.
Change listeners are for multi-threaded programming I think.
How about never changing the variable at all.
How about only accessing the variable through a function (or class method) that can handle whatever "listening" tasks you wanted to perform?
Why must you do:
$variable = 5;
?When you could do:
setMyVariable(5)
?If you want to implement own event handlers / triggers in array or anything else, then you might use class wrapper.
For one variable
__get()
and__set()
magic methods are enough, as you noticed. For array there is a better handler:ArrayAccess
. It allows to emulate array actions with class methods and common array semantics (like collections in some other languages).Shows:
I assume, that you might modify constructor in this code with array reference argument to be able to pass there superglobal array, like
$_COOKIE
. Another way is to replace$this->array
with$_COOKIE
directly within class. Also, there is a way to replace callables with anonymous functions.