I called Zend_Json::encode(), so WTH are all my properties?
The problem is simple, JSON encode a PHP object and send it back to the front end. Sounds simple and the last 100 times I wrote this code it was simple. This time, I was too smart for my own good. Here's the scenario. The object I'm encoding uses PHPs magic functions __get() and __set. __get() and __set() operate on a protected array named (drum roll please) $_data. (Stop me if you've heard this one)
class MyClass
{
protected $_data;
public function __get($index)
{
if (isset($this->_data[$index])) {
return $this->_data[$index];
}
return null;
} // public function __get($index)
public function __set($index, $value)
{
if (isset($this->_data[$index])) {
$this->_data[$index] = $value;
return true;
}
return false;
} // public function __set($index, $value)
}
So I instantiate an instance of MyClass and set a few very important properties:
$myObject = new MyClass();
$myObject->wifesBirthday = '5/14';
$myObject->nuclearLaunceCode = 'dontPushThisButton';
Now, var_dump($myObject) returns what you think it would, you can see the protected array and the values.
It was at this point that while I was still able to type coherent code, my brain had checked out for the night because even though the manual for Zend_Json::encode clearly states:
When encoding PHP objects as JSON, all public properties of that object will be encoded in a JSON object.
(See the problem here?)
In my mind, the properties existed...right? Cause I could set them; however, since I'm laying it out here for you, it's easy to see that since $_data is a protected property, it wasn't getting passed.
Using FireBug (is there a better FireFox extension? I don't think so) I could see that my PHP was handing back an empty JSON string to be re-constituted on the client side.
The solution, once I realized what was happening, was quite simple. just create an array of the properties you want to pass back.
$payload = array('wifesBirthday'=>$myObject->wifesBirthDay, 'nuclearLaunchCode'=>$myObject->nuclearLaunchCode);
$output = Zend_Json::encode($payload);
That was my first cut and low and behold it works. However, a better solution came to mind.
class MyClass
{
protected $_data;
public function __get($index)
{
if (isset($this->_data[$index])) {
return $this->_data[$index];
}
return null;
} // public function __get($index)
public function __set($index, $value)
{
if (isset($this->_data[$index])) {
$this->_data[$index] = $value;
return true;
}
return false;
} // public function __set($index, $value)
public function getProperties($skip=array())
{
$returnValue = array();
foreach($this->_data as $key=>$value) {
if (!in_array($key,$skip)) {
$returnValue[$key]=$value;
}
}
return $returnValue;
}
}
There, now I can simply write:
$payload = $myObject->getProperties();
$output = Zend_Json::encode($payload);
If I didn't want to disseminate the nuclear launch codes (I know I'm gonna start getting some weird searches now) I can write:
$payload = $myObject->getProperties(array('nuclearlaunchCode'));
$output = Zend_Json::encode($payload);
So I hope that by embarrassing myself publicly I can help at least one person. (For the record, it really only took me about 2 minutes to trace down the issue.)
=C=
Originally published on Postcards From My Life. Used by permission.
- Login or register to post comments
- 143 reads
- Flag as offensive
- Printer-friendly version






