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

Rainbet Konto Erstellen: A Practical Guide to Crypto Casino Sessions

The first thing most players notice about Rainbet is the sheer scale of what’s on offer. With over 8,000 casino games, a full sportsbook,...

Hvorfor spille live casino i stedet for RNG-spil?

IntroduktionLive casino-spil er blevet mere populære blandt spillere i Danmark, især blandt begyndere, der søger en mere autentisk spiloplevelse. I modsætning til RNG-spil, hvor...

At finde det bedste udbetalingscasino: Analyse af operatørers udbetalingsprocenter

IntroduktionNår det kommer til online gambling, er valget af det rigtige casino afgørende for at maksimere ens gevinster. For erfarne spillere i Danmark er...

Your ultimate guide to fast withdrawals at Interac Casinos Canada 2026: play and cash

The world of online casinos continues to evolve, and fast withdrawals have become a top priority for players in Canada. As we step into...

Waarom JumboSpin de ideale keuze is voor nieuwe spelers in 2026

In de wereld van online gokken biedt JumboSpin een scala aan mogelijkheden voor nieuwe spelers die op zoek zijn naar een spannende en veilige...