( ! ) Deprecated: Function set_magic_quotes_runtime() is deprecated in /home/charles/public_html/blarg/index.php on line 17
Call Stack
#TimeMemoryFunctionLocation
10.0002638432{main}( )../index.php:0

( ! ) Deprecated: Function set_magic_quotes_runtime() is deprecated in /home/charles/public_html/blarg/mysql.inc.php on line 7
Call Stack
#TimeMemoryFunctionLocation
10.0002638432{main}( )../index.php:0
20.0006640136include_once( '/home/charles/public_html/blarg/lib.inc.php' )../index.php:29
30.0007648552include_once( '/home/charles/public_html/blarg/mysql.inc.php' )../lib.inc.php:7
Plehnetoid - The Blog of of Charles Capps
 

The PHP5 ArrayObject

Work Fri Dec 29, 2006 @ 17:20 Pacific

It's a rare time when I can actually praise PHP. As a native Perl hacker, I've come to hate many aspects of the language because they just seem so horribly wrong. That isn't to say that there aren't things that are done right, it's just that the irritations are more than the benefits.

Here's a prime example. PHP5 allows what it calls overloading of object methods and properties. It's not what I'm used to thinking of when I hear the term "overload," but it's pretty interesting.

The long and short of it is that you can have code be called whenever:
1) A method is called that has not been defined
2) A property is accessed that does not exist or has not been declared public.

There's a high degree of utility here, if it's done right. An actual example that we use at work is using __get and __set to keep track of property changes, so that when the object is saved to the database, we can log what changed without actually comparing the object to itself, or keeping revisioning within the object.

Unfortunately PHP, logically, doesn't do it right. When the property is an array, __set is never called. This is because __get (or direct access) will return the array by reference, so changing an index in the array is done directly.

I'd previously blown off the Standard PHP Library as nothing more than OO wankery that was mostly useless in day to day coding. And while I still maintain that opinion to some extent, it does contain one gem that can fix the __set problem: ArrayObject.

An ArrayObject is not unlike a Perl tied array. There are four really important methods - offsetExists, offsetGet, offsetSet, and offsetUnset. There are a handful of others, but those are the interesting ones. The object is treated as an honest to goodness array by all PHP functions, and can be accessed directly as an array. Any additional methods can also be accessed directly through the normal object syntax.

(For additional fun, you can define its own __get and __set that call offsetGet and offsetSet so you can refer to each index in the array using both object syntax and array syntax.)

So how does this solve the __set problem? Simple -- override the default offsetSet method with some variety of logging, and add a method to fetch the changelog.

class LoggingArray extends ArrayObject {

private $log = array();

function offsetSet($index, $value) {
$old_value = $this->offsetGet($index);
if($old_value != $value)
$this->log[$index] = $old_value;
return parent::offsetSet($index, $value);
} // end offsetSet

function get_log() {
$log_array = array();
foreach($this->log as $k => $v) {
$log_array[] = "'$k' changed from '$v' to '{$this->offsetGet($k)}'";
} // end foreach
return join("\n", $log_array);
} // end get_log

} // end CC_Array

class Example {
public $test;
function __construct() {
$this->test = new LoggingArray;
} // end __construct
} // end Example

$x = new Example;
$x->test[0] = 2;
$x->test["hi"] = "there";
echo $x->test->get_log();


It'll be interesting to see how or if this will work in practice, and what kind of overhead is introduced by all those method calls.

[]

So, yeah

Work Wed Nov 22, 2006 @ 00:40 Pacific

Quite a bit has happened since I last actually updated this thing. First and foremost, as this one is going in the work category, I left my job at Groupee. The UBB was my passion for many years, but that passion was extinguished by so many things, internal and external. In the end, I think it was the right decision for both me and the product that was eventually released. The product has little resemblance to what I was set out to build, and despite it having a little of my code, it's not me, and it's not mine. This means that I want nothing to do with it, so you guys can stop harassing me about doing code hacking for it. Please.

I'm now working for Silicon Mechanics, as part of a team constantly improving their internal management tools. I've only been there a short while, but I'm already appreciating the difference of working on software for a limited audience and in a controlled environment. Never have I been so happy to be told I can skip cross-browser compatibility testing for backend portions of the code. IE can burn in hell, muahaha.

[]

Eve launches; new Infopop.com

Work Mon Jan 26, 2004 @ 20:35 Pacific

Eve!

Infopop.com!

Visit. Read. Buy. :)

[]
Software, Content, and Design © 2001-2004 Charles Capps