. */ /** * Doctrine_DB * A thin layer on top of PDO * * @author Konsta Vesterinen * @license LGPL * @package Doctrine */ class Doctrine_DB2 implements Countable, IteratorAggregate { /** * default DSN */ const DSN = "mysql://root:dc34@localhost/test"; /** * @var array $instances all the instances of this class */ protected static $instances = array(); /** * @var array $isConnected whether or not a connection has been established */ protected $isConnected = false; /** * @var string $dsn data source name */ protected $dsn; /** * @var string $username database username */ protected $username; /** * @var string $password database password */ protected $password; /** * @var PDO $dbh the database handler */ protected $dbh; /** * @var Doctrine_DB_EventListener_Interface|Doctrine_Overloadable $listener listener for listening events */ protected $listener; private static $driverMap = array("oracle" => "oci8", "postgres" => "pgsql", "oci" => "oci8"); /** * constructor * * @param string $dsn data source name * @param string $username database username * @param string $password database password */ public function __construct($dsn,$username,$password) { $this->dsn = $dsn; $this->username = $username; $this->password = $password; $this->listener = new Doctrine_DB_EventListener(); } /** * getDBH */ public function getDBH() { return $this->dbh; } /** * getDSN * returns the data source name * * @return string */ public function getDSN() { return $this->dsn; } /** * getUsername * * @return string */ public function getUsername() { return $this->username; } /** * getPassword * * @return string */ public function getPassword() { return $this->password; } /** * addListener * * @param Doctrine_DB_EventListener_Interface|Doctrine_Overloadable $listener * @return Doctrine_DB */ public function addListener($listener, $name = null) { if( ! ($this->listener instanceof Doctrine_DB_EventListener_Chain)) $this->listener = new Doctrine_DB_EventListener_Chain(); $this->listener->add($listener, $name); return $this; } /** * getListener * * @return Doctrine_DB_EventListener_Interface|Doctrine_Overloadable */ public function getListener() { return $this->listener; } /** * setListener * * @param Doctrine_DB_EventListener_Interface|Doctrine_Overloadable $listener * @return Doctrine_DB */ public function setListener($listener) { if( ! ($listener instanceof Doctrine_DB_EventListener_Interface) && ! ($listener instanceof Doctrine_Overloadable)) throw new Doctrine_DB_Exception("Couldn't set eventlistener for database handler. EventListeners should implement either Doctrine_DB_EventListener_Interface or Doctrine_Overloadable"); $this->listener = $listener; return $this; } /** * connect * connects into database * * @return boolean */ public function connect() { if($this->isConnected) return false; $this->dbh = new PDO($this->dsn,$this->username,$this->password); $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->dbh->setAttribute(PDO::ATTR_STATEMENT_CLASS, array("Doctrine_DB_Statement", array($this))); $this->isConnected = true; return true; } /** * getConnection * * @param string $dsn PEAR::DB like DSN or PDO like DSN * format for PEAR::DB like DSN: schema://user:password@address/dbname * * @return */ public static function getConnection($dsn = null, $username = null, $password = null) { $md5 = md5($dsn); if( ! isset(self::$instances[$md5])) { if(isset($username)) { self::$instances[$md5] = new self($dsn, $username, $password); } else { if( ! isset($dsn)) $a = self::parseDSN(self::DSN); else $a = self::parseDSN($dsn); extract($a); self::$instances[$md5] = new self($dsn, $user, $pass); } } return self::$instances[$md5]; } /** * driverName * converts a driver name like (oracle) to appropriate PDO * driver name (oci8 in the case of oracle) * * @param string $name * @return string */ public static function driverName($name) { if(isset(self::$driverMap[$name])) return self::$driverMap[$name]; return $name; } /** * parseDSN * * @param string $dsn * @return array Parsed contents of DSN */ function parseDSN($dsn) { // silence any warnings $parts = @parse_url($dsn); $names = array('scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment'); foreach($names as $name) { if( ! isset($parts[$name])) $parts[$name] = null; } if(count($parts) == 0 || ! isset($parts['scheme'])) throw new Doctrine_DB_Exception('Empty data source name'); $drivers = self::getAvailableDrivers(); $parts['scheme'] = self::driverName($parts['scheme']); if( ! in_array($parts['scheme'], $drivers)) throw new Doctrine_DB_Exception('Driver '.$parts['scheme'].' not availible or extension not loaded'); switch($parts['scheme']) { case 'sqlite': if(isset($parts['host']) && $parts['host'] == ':memory') { $parts['database'] = ':memory:'; $parts['dsn'] = 'sqlite::memory:'; } break; case 'mysql': case 'informix': case 'oci8': case 'mssql': case 'firebird': case 'pgsql': case 'odbc': if( ! isset($parts['path']) || $parts['path'] == '/') throw new Doctrine_DB_Exception('No database availible in data source name'); if(isset($parts['path'])) $parts['database'] = substr($parts['path'], 1); if( ! isset($parts['host'])) throw new Doctrine_DB_Exception('No hostname set in data source name'); $parts['dsn'] = $parts["scheme"].":host=".$parts["host"].";dbname=".$parts["database"]; break; default: throw new Doctrine_DB_Exception('Unknown driver '.$parts['scheme']); } return $parts; } /** * clear * clears all instances from the memory * * @return void */ public static function clear() { self::$instances = array(); } /** * errorCode * Fetch the SQLSTATE associated with the last operation on the database handle * * @return integer */ public function errorCode() { return $this->dbh->errorCode(); } /** * errorInfo * Fetch extended error information associated with the last operation on the database handle * * @return array */ public function errorInfo() { return $this->dbh->errorInfo(); } /** * prepare * * @param string $statement */ public function prepare($statement) { $this->connect(); $args = func_get_args(); $this->listener->onPrePrepare($this, $args); $stmt = $this->dbh->prepare($statement); $this->listener->onPrepare($this, $args); return $stmt; } /** * query * * @param string $statement * @return Doctrine_DB_Statement|boolean */ public function query($statement, array $params = array()) { $this->connect(); $this->listener->onPreQuery($this, $params); if( ! empty($params)) $stmt = $this->dbh->query($statement)->execute($params); else $stmt = $this->dbh->query($statement); $this->listener->onQuery($this, $params); return $stmt; } /** * quote * quotes a string for use in a query * * @param string $input * @return string */ public function quote($input) { $this->connect(); return $this->dbh->quote($input); } /** * exec * executes an SQL statement and returns the number of affected rows * * @param string $statement * @return integer */ public function exec($statement) { $this->connect(); $args = func_get_args(); $this->listener->onPreExec($this, $args); $rows = $this->dbh->exec($statement); $this->listener->onExec($this, $args); return $rows; } /** * fetchAll * * @return array */ public function fetchAll($statement, array $params = array()) { return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC); } public function fetchOne($statement, array $params = array()) { return current($this->query($statement, $params)->fetch(PDO::FETCH_NUM)); } public function fetchRow($statement, array $params = array()) { return $this->query($statement, $params)->fetch(PDO::FETCH_ASSOC); } public function fetchArray($statement, array $params = array()) { return $this->query($statement, $params)->fetch(PDO::FETCH_NUM); } public function fetchColumn($statement, array $params = array()) { return $this->query($statement, $params)->fetchAll(PDO::FETCH_COLUMN); } public function fetchAssoc($statement, array $params = array()) { return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC); } public function fetchBoth($statement, array $params = array()) { return $this->query($statement, $params)->fetchAll(PDO::FETCH_BOTH); } /** * lastInsertId * * @return integer */ public function lastInsertId() { $this->connect(); return $this->dbh->lastInsertId(); } /** * begins a transaction * * @return boolean */ public function beginTransaction() { $this->listener->onPreBeginTransaction($this); $return = $this->dbh->beginTransaction(); $this->listener->onBeginTransaction($this); return $return; } /** * commits a transaction * * @return boolean */ public function commit() { $this->listener->onPreCommit($this); $return = $this->dbh->commit(); $this->listener->onCommit($this); return $return; } /** * rollBack * * @return boolean */ public function rollBack() { $this->connect(); $this->dbh->rollBack(); } /** * getAttribute * retrieves a database connection attribute * * @param integer $attribute * @return mixed */ public function getAttribute($attribute) { $this->connect(); $this->dbh->getAttribute($attribute); } /** * returns an array of available PDO drivers */ public static function getAvailableDrivers() { return PDO::getAvailableDrivers(); } /** * setAttribute * sets an attribute * * @param integer $attribute * @param mixed $value * @return boolean */ public function setAttribute($attribute, $value) { $this->connect(); $this->dbh->setAttribute($attribute, $value); } /** * getIterator * * @return ArrayIterator */ public function getIterator() { return new ArrayIterator($this->queries); } /** * count * returns the number of executed queries * * @return integer */ public function count() { return count($this->queries); } }