PHP, Reflection and JSON: stream your objects
Amongst all the improvements in PHP 5 is the concept of Reflection. If you’re a Java person, you will be familiar with this concept.
In just a few words, Reflection means that Objects are open to (self-) inspection, so that you can interrogate an object for all kinds of properties at runtime.
Now if you have classes with getter (and setter) methods, there are some very elegant techniques with reflection. Normally, these getters and setters are used to give access to the data contained in the object. Good Object Oriented practice makes use of these Data Objects to build a clean boundary between the data and implementation details.
So, let’s assume that you have painfully crafted a class definition with accessors and you want to serialize the contained data as JSON over the wire. Of course, you can write a getJsonString() method for every class. But Reflection gives you a much nicer option.
An example of serialization into JSON, entirely based on Reflection:
function toDataObj($myObj) { $ref = new ReflectionClass($myObj); $data = array(); foreach (array_values($ref->getMethods()) as $method) { if ((0 === strpos($method->name, "get")) && $method->isPublic()) { $name = substr($method->name, 3); $name[0] = strtolower($name[0]); $value = $method->invoke($myObj); if ("object" === gettype($value)) { $value = toDataObj($value); } $data[$name] = $value; } } return $data; } print json_encode(toDataObj($myObj));
What is going on here?
First, I have a data object, referenced by $myObj, with a couple of getter methods.
Then, a new reflection object is instantiated for myObj. This reflection object contains a whole lot of reflection methods, of which getMethods() is used here.
In the foreach loop, a every method of the myObj is inspected in turn. Here we look for methods whose name start with “get” (the name property). Then we normalize the name (getMyVariable => myVariable) and call the original method of myObj through invoke($myObj).
If the returned value is an object itself, the function toDataObj is recursively called with this object.
Then, the name, value pair is stored in a hash list (called Array in PHP).
Finally, this hash is serialized into JSON.
The cool thing is that this function is really universal.
It will take just any object with getter methods and due-fully serialize the data, which then can be turned into a JSON stream, ready to consume in your Ajax applications.
Reflection class
The Reflection class and all of its subclasses are available in PHP 5.1.x, no need to include anything.
PHP JSON
If you’re running PHP 5.1.x, you most likely have json_encode() available, but you may need to enable the php_json extension in php.ini.
Otherwise download, build and install the extension and add the line extension=php_json.so (*nix) or extension=php_json.dll (Win32) in php.ini and you should be up and running.