Database Wrapper para PDO +(comentario sobre performance)

Os traigo un Wrapper que uso habitualmente en mis proyectos PHP. Lo suelo tener integrado en mi esqueleto Slim 3 pero lo he usado con anterioridad en otros tipos de proyectos. Seria un sustituto del ORM que nunca me ha gustado usar. Lo he ido programando con el tiempo y las funciones insert, update y delete las cogí de algún otro Wrapper, ORM o a saber.

En mis proyectos es importante que el acceso a la base de datos sea rápido y muchas veces el uso de un ORM como Doctrine o Eloquent no son para nada rápidos:

With pure PDO:
memory: 0.0044288635253906
seconds: 0.24748301506042

With DBAL and autoload:
memory: 0.97610473632812
seconds: 0.29042816162109

Extraído de Reddit y de gonzalo123.com. No es el código mas elegante ni de la ultima versión de PHP, de hecho tengo que actualizarlo para poder usar toda la potencia de PDO, aun así, aquí os lo pego y luego un tutorial de como usarlo (os prometo que lo actualizare para sacarle mas jugo):

class DatabaseWrapper {

    private $_conn;

    public function __construct( $db )
    {

        $pdo                = new PDO($db, $db, $db, $db);

        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

        $this->_conn        = $pdo;

    }

    protected function exec($query, $params)
    {

        if (strpos($query,'SELECT') !== false) {
            return $this->executeQuery($query, $params)->fetchAll(\PDO::FETCH_ASSOC);
        }

        return $this->executeQuery($query, $params)->rowCount();

    }

    protected function executeQuery($query, $params) {

        $statment  = $this->_conn->prepare($query);
        $statment->execute($params);

        return $statment;

    }

    public function fetchRow($query, $params = array()) {

        return $this->executeQuery($query,$params)->fetch(\PDO::FETCH_ASSOC);

    }

    public function fetchAll($query, $params) {

        return $this->executeQuery($query,$params)->fetchAll(\PDO::FETCH_ASSOC);

    }

    public function fetchColumn($query, $params, $column = 0) {

        return $this->executeQuery($query,$params)->fetchColumn($column);

    }

    public function fetchAssoc($statement, array $params = array())
    {
        return $this->executeQuery($statement, $params)->fetch(\PDO::FETCH_ASSOC);
    }

    public function fetchArray($statement, array $params = array())
    {
        return $this->executeQuery($statement, $params)->fetch(\PDO::FETCH_NUM);
    }

    public function delete($tableExpression, array $identifier, array $types = array())
    {
        if (empty($identifier)) {
            return FALSE;
        }

        $criteria = array();

        foreach (array_keys($identifier) as $columnName) {
            $criteria[] = $columnName . ' = ?';
        }

        return $this->exec(
            'DELETE FROM ' . $tableExpression . ' WHERE ' . implode(' AND ', $criteria),
            array_values($identifier)
            //is_string(key($types)) ? $this->extractTypeValues($identifier, $types) : $types
        );
    }

    public function insert($table, $data)
    {
        $fields = $values = array();
        foreach ($data as $key => $value) {

            if ($value instanceof DateTime) {
                $value = $value->format('Y-m-d H:i:s');
            }

            $fields[] = '`'.str_replace("`", "``", $key).'`';
            $values[] = $this->_conn->quote($value);
        }

        $query = "INSERT INTO `$table` (".implode(',', $fields).") VALUES (".implode(',', $values).")";

        $this->_conn->exec($query);

        return $this->_conn->lastInsertId();
    }

    public function update($table, $data, $conditions)
    {
        if (!$data) {
            return false;
        }

        $updates = $wheres = array();
        foreach ($data as $key => $value) {

            if ($value instanceof DateTime) {
                $value = $value->format('Y-m-d H:i:s');
            }

            $updates[] = '`'.str_replace("`", "``", $key).'` = '.$this->_conn->quote($value);
        }

        foreach ($conditions as $key => $value) {
            $wheres[] = '`'.str_replace("`", "``", $key).'` = '.$this->_conn->quote($value);
        }

        $table = '`'.str_replace("`", "``", $table).'`';

        $query = "UPDATE $table SET ".implode(', ', $updates)." WHERE ".implode(' AND ',$wheres);

        $this->_conn->exec($query);

        return true;
    }

    public function query($statement)
    {

        return $this->_conn->exec($statement);

    }

    public function errorCode()
    {
        return $this->_conn->errorCode();
    }

    public function errorInfo()
    {
        return $this->_conn->errorInfo();
    }

    public function lastInsertId($seqName = null)
    {
        return $this->_conn->lastInsertId($seqName);
    }

}

SELECT de una fila

$dbw      = new DatabaseWrapper($db);
$sql        = 'SELECT `name`, email FROM Users WHERE id = ?';

$user      = $dbw->fetchRow($sql, );

SELECT

$dbw      = new DatabaseWrapper($db);
$sql        = 'SELECT `id`, `room`, beds
                              FROM Rooms WHERE hotel_id = ?';

$rooms      = $dbw->fetchAll($sql, );

DELETE

$dbw      = new DatabaseWrapper($db);
$dbw->delete($table_name, );

INSERT

$dbw      = new DatabaseWrapper($db);
$row_id  = $dbw->insert($table_name, );

UPDATE

$dbw      = new DatabaseWrapper($db);
$row_id  = $dbw->update($table_name, ,);

Resumen de metodos:

    • fetchRow
    • fetchAll
    • fetchColumn
    • fetchAssoc
    • fetchArray
    • delete
    • insert
    • update
    • query
    • errorCode
    • errorInfo
    • lastInsertId

Nunca hago el new en el código porque mis proyectos funcionan con DI y el objeto $dbw siempre me llega al controlador. Si os interesa esta técnica os podría explicar como.

PandaGG
Lok'tar ogar

Dejar respuesta

Please enter your comment!
Please enter your name here

Sponsor

Últimos

Avance de Horizon Forbidden West

Avance de Horizon Forbidden West El año 2022 ha empezado fuerte en consolas, y los próximos meses estarán repletos de potentísimos lanzamientos. Uno de los...

Los mejores juegos de Android en 2021

Llega el momento de echar la vista atrás y repasar lo mejor que nos ha dejado 2021. Y hoy queremos hacerlo sobre uno de...

Avance de Hogwarts Legacy

Aunque este ambicioso RPG tuvo su primer anuncio hace bastante más de un año, con motivo del anuncio de los juegos que vería la...

Mejores mandos gaming para PC

Aunque es cierto que para muchos juegos la combinación de teclado y ratón es insuperable, no es menos cierto que muchos otros juegos ofrecen...

Los 6 juegos más esperados de 2022 para PC

El año 2021 va quedando atrás, y aunque los proyectos de videojuegos en PC son muchos cada año, son unos pocos los que acaparan...