Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Daniel O'Connor http://clockwerx.blogspot.com/

« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS 

PEAR::DB, DataObjects, and Joins / Reflection

PEAR::DB_DataObject is great. I really like it. We don't use it at work, though; having gone for a slightly different route. This pattern should be applicable, however, quite nicely to DB_DataObject.

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:
<?php
require_once 'DB.php';

$db = DB::connect("mysql://blah:blah@server/databaseName"); //Defined elsewhere
$db->setFetchMode( DB_FETCHMODE_ASSOC );


?>


Next, we have our core object.
<?php
class Core {


    /**
     * Process and extract values from an associative array.
     *
     * Improve performance and overload in child classes.
     *
     * @param   mixed[]    $array  Typically an assoc array from a DB::result->fetchRow.
     * @return  bool
     */
    public function updateFromArray($array) {
                
        if ( is_array($array) ) {

            $class = new ReflectionObject($this);
            $properties = $class->getProperties();

            for ($i = 0; $i < count($properties); $i++) {
                $prop_name = $properties[$i]->getName();

                if (array_key_exists($prop_name, $array)) {
                    $this->$prop_name = @$array[$prop_name];
                }
            }
        }

        return true;
    }
}
?>


So, when we do a query we can mash up everything nicely (assuming we don't have two tables with the same column names):

$sql = "SELECT * FROM table t JOIN table2 t2 ON t.table_id = t2.table_id";

$result = $db->query($sql);

while ($row = $result->fetchRow()) {
   $t = new Table();
   $t2 = new Table2();

   $t->updateFromArray($row);
   $t2->updateFromArray($row);

   //Do whatever you like with your objects...
}


... and our objects get efficiently populated with data in a single query.

The behind the scenes magic...
class Table extends DO_Table {
//Business logic
}

class Table2 extends DO_Table2 {
//Business logic
}

class DO_Table extends DB_DataObject {
     public $field;
}


class DO_Table extends DB_DataObject {
     public $field2;
}

class DB_DataObject extends Core {
     
}


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.

All Exceptions Created Equal

All exceptions are created equal. But what if you have a very good and pressing reason to serialize one to save it in a database? For instance, you had a collection of checks you wanted to run against some data, and save the results?

Ah, that's easy! serialize() was made for that! So off you trot, you make a few changes to the code, add a blank line here, a blank line there, and suddenly your code can't find the exact matches of the serialized object in the database.

HUH? What's going on? You're the exact same Exception I just threw three minutes ago, and you've sporadically broken?

It took me a while to twig. When you create an exception ($e = new Exception("foo");), it's shiny and new and listens when you do equality comparisions (==).

But things go awry: you throw a new Exception from your filter, catch it, and serialize it. You haven't remembered that...


$a = new Exception("foo");
try {
    throw $a; //Line 1
} catch (Exception $e) {
    throw $a; //Line 10;
}



will result in two difference traces. One saying "I was thrown on on line 1", the other "I was thrown on on line 10"...

Fuck oath, hello stupid coder. You've been wracking your brains wondering why every time you go off and edit a different bit of code it serializes differently; and there you have it.

How the hell do I fix it? Going to __sleep() on the job actually helps.



<?php
class DumbException extends Exception {
    /**
     * Cleanup anything we need before serialisation
     *
     * @return  string[]    An array of member varible names to serialize
     * @see     http://php.planetmirror.com/manual/en/language.oop5.magic.php
     */
    public function __sleep() {
        return array('string','code');
    }

    /**
     * Compare against another DumbException for equality.
     *
     * Since two exceptions can be !== because the trace / line / file
     * information is different, we need to do this.
     */
    public function cmp(DumbException $e) {
        return (serialize($e) == serialize($this));
    }
}

print '<pre>';
$a = new DumbException();
$b = new DumbException();


try {
    try {
        throw $b;
    } catch (Exception $e) {
        throw $a;
    }
} catch (Exception $e) {

    var_dump($a === $b);
    var_dump($a == $b);
    var_dump($b === $e);
    var_dump($b == $e);
    var_dump($a === $e);
    var_dump($a == $e);

    var_dump($b->cmp($e));
    var_dump($a->cmp($e));
}
print '</pre>';
?>

Ninging It

I love http://www.ning.com/ - and I fell in love with chaining whole bunches of objects together.


class Foo {
    function transform() {
         //Some actual code
         return $this;
    }

    function transform2() {
         //Some actual code
         return $this;
    }

}

$f = new Foo();
$f->transform()->transform2()->transform();


Concise!
« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS