JSON, or JavaScript Object Notation, is fairly popular.
This is just my modest take on a ‘PHP Object Notation’ implementation.
Note that it is meant to follow how your mind works rather than being syntactically correct; therefore, associative arrays are used in a loose manner where you have to worry about associative syntax as little as possible.
Basically, type away until your object is fully described.
Here is a notation sample:
.
This syntax can then be used the same way JSON is used, using eval. Here is how and you will immediately notice how the eval() syntax has to differ from the JavaScript one:
$remote_str = <<<EOB array( 'root level' => array( 'sublevel 1' => array( 'sublevel 2' => 'sublevel 3', ), ) ); EOB; // ... eval('$local_str='.$remote_str.';'); |
.
Feels a bit clumsy. Fortunately, starting with PHP4, if you are not too sad about introducing a statement in your remote string, you can rewrite it like this:
$remote_str = <<<EOB return array( 'root level' => array( 'sublevel 1' => array( 'sublevel 2' => 'sublevel 3', ), ) ); EOB; // ... $local_str = eval($remote_str); |
.
Better, isn’t it?
In this last listing, you will find the very simple code I wrote to traverse the object. Note that I invoke a callback for every element, otherwise this code would not be very helpful.
Note that this is just a concept for something I needed to throw together quickly therefore there are some limitations; for instance, you cannot have numeric keys since in this context their “keyness” is ignored and even feared.
<?php function traverse_tree($callback, $curlevel, $curdepth, $uid) { $depthstr = '------------------------------------------------------------------------------'; $padding = substr($depthstr, 0, $curdepth); if(!is_array($curlevel)) { $callback($curlevel, $padding, $uid); return; } foreach($curlevel as $level=>$children) { if(!is_numeric($level)) { $my_uid = $callback($level, $padding, $uid); traverse_tree($callback, $children, $curdepth + 2, $my_uid); } else { $callback($children, $padding, $uid); } } } function do_something($name, $padding, $uid) { $iid = 0; // Bogus value print $padding.$name." ($iid)n"; return $iid; } // ----------------------------------------------------------- // Here we go // ----------------------------------------------------------- if(count($argv) != 2) die("nSyntax: ".$PHP_SELF." 'root_node_name'nn"); $rootnodename = &$argv[1]; $INS = array( $rootnodename => array( 'Bikes' => array( 'Yamaha' => 'Fz', 'Honda', 'Norton' ), 'Trikes', 'Cars' => array( 'Chevrolet' => array( 'Corvette' => array('Z06', 'Convertible', 'Coupe'), 'Camaro', 'Jimmy' ), 'Ford' => array( 'Mustang' => array('GT', 'Premium', 'Shelby', 'Other'=>'Roush'), 'Explorer', 'Crown Victoria' ), 'Chrysler' => array( 'Dodge' => 'Charger', '300X', 'Le Baron' ), ) ) ); traverse_tree(do_something, $INS, 0, 1); print "DONEnn"; ?> |
.
Invoke with:
php my_php_script.php "Vehicles" |
.
“What is this $iid variable?” you may ask.
You will notice that this piece of code is particularly convenient if you want to add a whole tree structure to your database. Say the you are using MySQL and want to create categories and sub-categories, using the column ‘pid’ as a category’s parent id. You would rewrite do_something:
function do_something($name, $padding, $uid) { mysql_query("INSERT INTO my_cat_table(pid, title) VALUES({$uid}, '{$name}')"); $iid = mysql_insert_id(); print $padding.$name." ($iid)n"; return $iid; } |
Voila!
If you enjoyed this post, make sure you subscribe to my RSS feed!






thats it, guy
So you stacked some arrays up in a sting and eval()ed the string… Doesn’t seem right, firstly for requiring eval() and secondly for just eval()ing a string. Am I missing the point? Javascript has that even without JSON.
It’s nice that it works with a minimal amount of code, but the problems here are plentiful:
1) PHP already has the serialize() function, which does exactly what you’re talking about _and_can_hold_objects_and_pretty_much_anything_else_in_it_you_like_ – and is marginally more secure than eval()
2) Where is this kind of data going to come from? The main point of JSON is to move data across the internet – are you going to eval() data on your server that you’ve received through the internet? I hope not. If not, it’s not really an answer to JSON is it?
3) If only PHP understands it, it’s not really much use is it? As noted above, PHP already serializes far more interesting things than arrays. And it does it in compiled code, too, so it’s probably faster. Are you reinventing the wheel?
4) A nice format for shipping data between applications client-side and serverside has actually already been developed and is implemented in many languages including Python and PHP. That notation is… (drumroll) … JSON. Sure, you need an extension, but I’d rather just use the nice standard JSON extension than cook up my own black magic, hacky implementation.
As an aside, on line ~36 of the 4th block of code you used double quotes to terminate a string literal, but you used the concatenation operator to insert a variable into it. Nobody’s code is perfect, least of all mine, and that’s such a dumb thing to notice or care about but it is one of my pet hates because not only is it less efficient to parse that, it’s also more difficult to write (as you used between two and four more keystrokes than what you would have used if you’d done it properly, plus it’s not quite as readable)…
Your other articles are all fantastic. I loved them, I learned from them, I was inspired by them. But with this particular one, I just don’t get it.
Well, that article was written mostly in jest — do not give it too much credit, I was just blowing some steam as I had spent the previous week working exclusively with SOAP
Obviously if I were to use something like this, it would be between two trusted servers, not for web clients; but I wouldn’t even use this guy as there are other existing lightweight solutions that fit the bill, such as JSON (indeed) or YAML. Even XML-RPC is lightweight compared to a full-on SOAP exchange.
Again, after spending a week with SOAP, this was just a — liberating — exercise in finding an implementation that would be its exact opposite: as little overhead as possible
Wouldn’t waiting for PHP 5.3 to become a stable release and doing Lambda functions (anonymous functions) be better than doing eval? From the examples I have looked over, it seems we could do the following. I may be completely wrong on this, since I don’t have a 5.3 RC installed.
function($x)
{
return($x*10);
});
echo $arr['somFunction'](5);
With closures you could do more with the ‘use’ keyword.
$arr = array(‘val1′ => 0,
‘val2′ => 0′,
‘func’ => function()use(&$arr)
{
return($arr['val1']*$arr['val2']);
});
$arr['val1] = 5;
$arr['val2] = 10;
echo $arr['func']();
Like I said, I could be completely wrong and/or there could be a better way, like using a keyword would that would represent (this or self) to reference the array.
@EllisGL –
I do not know if your syntax works with 5.3 but it sure makes sense, obviously.
Note that, as mentioned earlier, I had written this piece mostly tongue-in-cheek because SOAP was slowly killing me inside!
@admin – I completely understand.