* @version 0.1
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
/**
* Database Connector
*
* @since 0.1
*/
class DbConnector { // extends HelpableSingleton
protected $connector;
protected $critical;
protected $debug;
protected $sqlQueryCount;
public function __construct() {
$this->debug = APP_DB_DEBUG;
$this->critical = APP_DB_CRITICAL;
$this->sqlQueryCount = 0;
}
// ---- Managing CONNECTION --------------------------------------------------
/**
* get DB connection
*/
public static function getConnection($i=0) {
// -TODO-
// connections shouldn't be hold by the front controller,
// but by this class instantiated as a singleton
$fc = FrontController::getInstance();
if (empty($fc->db[$i])) {
throw new AppException('Connection #'.$i.' does not exists');
}
try {
if ($fc->db[$i]->isConnected()) {
return $fc->db[$i];
}
} catch (Exception $e) {
throw new AppException('Connection #'.$i.' not established : '.$e->getMessage());
}
}
protected function connectTheConnector(DbEngine $obj) {
$this->connector = $obj;
}
public function connect($host=APP_DB_HOST, $user=APP_DB_USER, $pass=APP_DB_PASS, $base=APP_DB_BASE) {
if ($this->connector) {
return true;
}
// not connected yet, just do it
$dbc = 'Db'.ucfirst(APP_DB_CONNECTOR);
$con = new $dbc($host, $user, $pass, $base);
if ($con->connect()) {
$this->connectTheConnector($con);
return true;
}
// reaching this point means an error as occured
// $this->reportError();
// return false;
echo 'Cannot connect to database "'.APP_DB_BASE.'" on host "'.APP_DB_HOST.'" with user "'.APP_DB_USER.'"';
exit;
}
public function isConnected() {
return is_a($this->connector, 'DbEngine');
}
public function setDbDebug($level) {
$this->debug = $level;
}
public function setDbCritical($mode=true) {
$this->critical = $mode;
}
// ---- QUERYING the Database ---------------------------------------------
public static function query($qry, $dbi=0) {
$db = self::getConnection($dbi);
return $db->_query($qry);
}
protected function _query($qry) {
$this->sqlQueryCount++;
switch ($this->debug) {
case 4:
FC::log_debug($qry);
break;
case 5:
echo "".$qry."
";
break;
}
if (preg_match("/^(SELECT|SHOW)/i",ltrim($qry))) {
$r = $this->connector->querySelect($qry);
} else {
$r = $this->connector->queryAffect($qry);
}
if ($r === false) {
// error !
$this->reportError($qry);
}
$this->setDbDebug(APP_DB_DEBUG); // back to normal debug level
return $r;
}
public function transactionQueries($arrSql) {
if (!is_array($arrSql)) {
if (empty($arrSql)) {
return false;
}
$arrSql = array($arrSql);
}
if (!$this->transactionBegin()) {
FC::log_warn('can not begin transaction');
}
$ok = true;
foreach($arrSql as $sql) {
if (!$this->query($sql)) {
$ok = false;
break;
}
}
if ($ok) {
return $this->transactionCommit();
} else {
$this->transactionRollBack();
return false;
}
}
// ---- MISCELLANEOUS --------------------------------------------------------
/**
* log or display DB errors in the browser
*/
public function reportError($qry='') {
if (empty($this->debug)) {
return false;
}
// if critical, should at least show an error code in browser
$debug = ($this->critical && $this->debug < 2)?2:$this->debug;
$html = '';
$str = 'DB Error #'.$this->connector->getErrorNo().' : '.$this->connector->getErrorMsg();
switch ($debug) {
case 2:
echo '
DB Error #'.$this->connector->getErrorNo().'
'; case 1: if ($qry) { FC::log_error($qry); } case 4: FC::log_error($str); break; case 3: if ($qry) { $htm = ''.htmlentities($qry).'';
}
case 5:
$htm = nl2br(htmlentities($str)).$htm;
break;
default:
echo 'DB DEBUG level undefined
'; break; } echo ''.$htm.'
'; if ($this->critical) { exit; } } /** * pass on undefined method to selected connector */ public function __call($name, $args) { if ($this->connector) { if (method_exists($this->connector, $name)) { return call_user_func_array(array($this->connector, $name), $args); } } throw new AppException('Unknown method '.$name.' in '.__CLASS__.' or in the Db Connector ('.APP_DB_CONNECTOR.')'); } } interface DbEngine { public function connect(); public function escapeString($str); public function querySelect($qry); public function queryAffect($qry); public function getTable($table); public function getErrorNo(); public function getErrorMsg(); }