ПДО класс-оболочку


<?php

class Database
{
    private $_dbh;
    private $_stmt;
    private $_queryCounter = 0;

    public function __construct($user, $pass, $dbname)
    {
        $dsn = 'mysql:host=localhost;dbname=' . $dbname;
        //$dsn = 'sqlite:myDatabase.sq3';
        //$dsn = 'sqlite::memory:';
        $options = array(
                    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
                    PDO::ATTR_PERSISTENT => true
                    );
        try {
            $this->_dbh = new PDO($dsn, $user, $pass, $options);
        }
        catch (PDOException $e) {
            echo $e->getMessage();
            exit();
        }
    }

    public function query($query)
    {
        $this->_stmt = $this->_dbh->prepare($query);
    }

    public function bind($pos, $value, $type = null)
    {
        if (is_null($type)) {
            switch (true) {
                case is_int($value):
                    $type = PDO::PARAM_INT;
                    break;
                case is_bool($value):
                    $type = PDO::PARAM_BOOL;
                    break;
                case is_null($value):
                    $type = PDO::PARAM_NULL;
                    break;
                default:
                    $type = PDO::PARAM_STR;
            }
        }
        $this->_stmt->bindValue($pos, $value, $type);
    }

    public function execute()
    {
        $this->_queryCounter++;
        return $this->_stmt->execute();
    }

    public function resultset()
    {
        $this->execute();
        return $this->_stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function single()
    {
        $this->execute();
        return $this->_stmt->fetch(PDO::FETCH_ASSOC);
    }

    // returns last insert ID
    //!!!! if called inside a transaction, must call it before closing the transaction!!!!!!
    public function lastInsertId()
    {
        return $this->_dbh->lastInsertId();
    }

    // begin transaction // must be innoDatabase table
    public function beginTransaction()
    {
        return $this->_dbh->beginTransaction();
    }

    // end transaction
    public function endTransaction()
    {
        return $this->_dbh->commit();
    }

    // cancel transaction
    public function cancelTransaction()
    {
        return $this->_dbh->rollBack();
    }

    // returns number of rows updated, deleted, or inserted
    public function rowCount()
    {
        return $this->_stmt->rowCount();
    }

    // returns number of queries executed
    public function queryCounter()
    {
        return $this->_queryCounter;
    }

    public function debugDumpParams()
    {
        return $this->_stmt->debugDumpParams();
    }

}

Тестирование класса....

/**
 * Establish a DB connection.
 */
$database = new Database('root', '', 'testing');


/**
 * Insert 1 new record
 */
$database->query('INSERT INTO testing (col1,col2,col3) VALUES (:name,:tag,:date)');
$database->bind(':name', 'john doe');
$database->bind(':tag', 'hi');
$database->bind(':date', 'may 1');
$database->execute();
//returns last auto increment ID
echo $database->lastInsertId();


/**
 * Insert 2 new records using Transactions
 * Also Bind new results without running $database->query() a second time
 */
$database->beginTransaction();
$database->query('INSERT INTO testing (col1,col2,col3) VALUES (:name,:tag,:date)');
$database->bind(':name', 'user 1');
$database->bind(':tag', 'hello');
$database->bind(':date', 'may 2');
$database->execute();

// Add second item to DB without runing $database->query() again
$database->bind(':name', 'user 2');
$database->bind(':tag', 'hello 2');
$database->bind(':date', 'may 22');
$database->execute();
//returns last auto increment ID
echo $database->lastInsertId();
//$database->cancelTransaction();
$database->endTransaction();


/**
 * Select a row of items from DB
 */
$database->query('SELECT col1, col2, col3 FROM testing WHERE id > ? LIMIT ?');
$database->bind(1, 1);
$database->bind(2, 5);
$row = $database->single();
echo "<pre>";
print_r($row);
echo "</pre>";


/**
 * Create a new query, bind values and return a resultset.
 */
$database->query('SELECT col1, col2, col3 FROM testing WHERE col2 = :col2 LIMIT :limit');
$database->bind(':col2', 'hello 2');
$database->bind(':limit', 10);
$rs = $database->resultset();

foreach ($rs as $row) {
    echo $row['col1'] . '<br>';
    echo $row['col2'] . '<br>';
    echo $row['col3'] . '<br>';
}


/**
 * Show number of queries executed on DB
 */
echo $database->queryCounter();
?>

Это то, что у меня до сих пор. Я хочу изменить его, Хотя, так что я могу запустить его больше, как это ниже вместо запуска отдельной привязки() методы для каждого элемента...

$query = 'INSERT INTO user(user_id, user_username, user_password)
        VALUES( :user_id, :user_username, :user_password))';
$args = array(
    ':user_id' => $data['user_id'],
    ':user_username' => $data['user_username'],
    ':user_password' => $data['user_password']
    );
$db->query($query, $args);


$query = "SELECT user_id FROM user WHERE user_username = :username LIMIT 1";
$results = $db->query($query, array(':username' => $username));

Может кто-то помочь изменить этот код, чтобы разрешить этот формат?

Я также обеспокоен новым методом. Мой текущий код позволяет мне подготовить заявление и привязать некоторые параметры и вставьте их, а затем связать еще несколько и вставить их без снова готовит заявление. Новый путь я хочу изменить его, чтобы бы убить эту функциональность?



4285
6
задан 2 августа 2011 в 05:08 Источник Поделиться
Комментарии
2 ответа

Я делаю некоторые незначительные замечания на этот старый вопрос.

Как вы сделали свой фантик коды ваш выбор без надобности.

Наблюдаем текущие конструктора:

public function __construct($user, $pass, $dbname)
{
$dsn = 'mysql:host=localhost;dbname=' . $dbname;
//$dsn = 'sqlite:myDatabase.sq3';
//$dsn = 'sqlite::memory:';
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
PDO::ATTR_PERSISTENT => true
);
try {
$this->_dbh = new PDO($dsn, $user, $pass, $options);
}
catch (PDOException $e) {
echo $e->getMessage();
exit();
}
}

Это понятно из ваших комментариев, что вы уже рассматриваете разные ДСН. Вы напрасно замок ПДО вниз к MySQL подключения localhost. Все эти параметры делают ваш класс менее многоразовые.

Ловить и призывая покинуть дальнейшей блокировки вашего класса вплоть до самоуничтожения. Это дает возможность кому-то использовать свой класс, увидеть, что база данных не подключить поймать исключение себя и справиться с ним так, как они хотят.

Что делает ваш класс нужен?

Он должен PDO-объекта (то есть все). Остальная часть класса не зависит, все настройки, которые вы сделали в конструкторе.

Поэтому, я бы построить свой объект PDO за пределами этого класса. Тогда ваш конструктор будет:

public function __constructor(PDO $pdo)
{
$this->_dbh = $pdo;
}

Гибкость и возможность многократного использования следует.

3
ответ дан 24 апреля 2012 в 04:04 Источник Поделиться

Я думаю, добавив новый метод к существующему классу и назвав существующий запрос,привязку и выполнение методов должно быть достаточно:

public function query2($query,$params)    {        
$this->query($query);
foreach($params as $k=>$v){
$this->bind($k, $v);
}
return $this->execute();
}

1
ответ дан 2 августа 2011 в 06:08 Источник Поделиться