2/6/10

Trabajando con objetos en base de datos con PDO y Mongo + Demo con Twig


Trabajar con resultados de bases de datos como si fuesen objetos permite trabajar de una forma muy cómoda e intuitiva. PDO tiene soporte nativo para devolver instancias de una clase en vez de arrays. Pero con MongoDB tampoco es mucho más complicado conseguir un iterador de objetos de una clase determinada.
Aquí coloco un ejemplo con PDO, Mongo y Twig. Con twig se ve claramente la comodidad de tener objetos con los que poder llamar métodos que produzcan datos derivados sin tenerlos que generar explícitamente (on demand).
He creado una clase derivada de IteratorIterator y un método estático usando late static binding para poder castear un array/objeto a una nueva instancia de una clase especificada.











class CastModelIteratorIterator extends IteratorIterator {
    public $class;

    function current() {
        return Model::cast(parent::current(), $this->class);
    }
}

class Model {
    static public function cast($array, $class = null) {
        $object = ($class === null) ? (new static) : (new $class);
        foreach ($array as $k => $v) $object->$k = $v;
        return $object;
    }
    
    static public function castIterator($iterator) {
        $iterator = new CastModelIteratorIterator($iterator);
        $iterator->class = get_called_class();
        return $iterator;
    }
}

class TestModel extends Model {
    public $name, $pass;

    function __construct($name = 'test') {
        $this->name = $name;
        $this->pass = self::hashPassword('test');
    }
    static function hashPassword($password) {
        return md5("{$password}*");
    }
    function checkPassword($password) {
        return $this->pass == self::hashPassword($password);
    }
    function url() {
        return sprintf('/user/%s', urlencode($this->name));
    }
}

// Sqlite PDO Test
{
    $db = new PDO('sqlite::memory:');
    $db->query('CREATE TABLE TestModel (name, pass);');
    $t = $db->prepare('INSERT INTO TestModel (name, pass) VALUES (?, ?);');
    $model = new TestModel('Test');
    $t->execute(array($model->name, $model->pass));
    foreach ($db->query('SELECT * FROM TestModel;', PDO::FETCH_CLASS, 'TestModel') as $e) {
        printf("%s\n", $e->url());
    }
}

// Mongo Test
{
    $mongo = new Mongo(); // connect
    $db = $mongo->demo;
    $collection = $db->TestModel;
    $collection->remove();
    $collection->insert(new TestModel('Test'));

    foreach (TestModel::castIterator($collection->find()) as $e) {
        printf("%s\n", $e->url());
    }
}

// Twig
{
    require_once(__DIR__ . '/Twig/Autoloader.php');
    Twig_Autoloader::register();
    $collection->insert(new TestModel('Demo'));

    $twig = new Twig_Environment(new Twig_Loader_String(), array(
        'debug'       => true,
        'auto_reload' => true,
    ));

    $twig->loadTemplate('
        <ul>{% for item in list %}
<li><a href="{{ item.url }}">User {{ item.name }}</a></li>
{% endfor %}</ul>
')->display(array(
        'list' => TestModel::castIterator($collection->find()),
    ));
}

No hay comentarios:

Publicar un comentario