PEAR::DB, DataObjects, and Joins / Reflection
First, the database is set to associative fetching - our results come out as neat little arrays with fieldnames, so a $row = $db->query(/*blah*/)->fetchRow(); makes $row["id"], $row["field"], etc...
Configuration:
1 2 <?php 3 require_once 'DB.php'; 4 5 $db = DB::connect("mysql://blah:blah@server/databaseName"); //Defined elsewhere 6 $db->setFetchMode( DB_FETCHMODE_ASSOC ); 7 8 9 ?>
Next, we have our core object.
1 2 <?php 3 class Core { 4 5 6 /** 7 * Process and extract values from an associative array. 8 * 9 * Improve performance and overload in child classes. 10 * 11 * @param mixed[] $array Typically an assoc array from a DB::result->fetchRow. 12 * @return bool 13 */ 14 public function updateFromArray($array) { 15 16 if ( is_array($array) ) { 17 18 $class = new ReflectionObject($this); 19 $properties = $class->getProperties(); 20 21 for ($i = 0; $i < count($properties); $i++) { 22 $prop_name = $properties[$i]->getName(); 23 24 if (array_key_exists($prop_name, $array)) { 25 $this->$prop_name = @$array[$prop_name]; 26 } 27 } 28 } 29 30 return true; 31 } 32 } 33 ?>
So, when we do a query we can mash up everything nicely (assuming we don't have two tables with the same column names):
1 2 $sql = "SELECT * FROM table t JOIN table2 t2 ON t.table_id = t2.table_id"; 3 4 $result = $db->query($sql); 5 6 while ($row = $result->fetchRow()) { 7 $t = new Table(); 8 $t2 = new Table2(); 9 10 $t->updateFromArray($row); 11 $t2->updateFromArray($row); 12 13 //Do whatever you like with your objects... 14 }
... and our objects get efficiently populated with data in a single query.
The behind the scenes magic...
1 2 class Table extends DO_Table { 3 //Business logic 4 } 5 6 class Table2 extends DO_Table2 { 7 //Business logic 8 } 9 10 class DO_Table extends DB_DataObject { 11 public $field; 12 } 13 14 15 class DO_Table extends DB_DataObject { 16 public $field2; 17 } 18 19 class DB_DataObject extends Core { 20 21 }
Now... there's a few gotchas with this; which is why we don't use DB_DataObject - you can accidentally overwrite information you shouldn't from Core::updateFromArray();
There's no validation - you have to trust the array data you pass to the object.
You have to watch your 'specialist' doesn't do anything silly like Table::updateFromArray($_REQUEST);
You are limited to one row, one *type* of object - you couldn't join a table to itself and such.