initHandler (); } /** * Opens a new connection to the database. * * @param string $host The host name * @param string $user The user name to authenticate * @param string $pass The user password * @param string $name The default schema name * * @return boolean %TRUE on success, %FALSE otherwise **/ function open ($host, $user, $pass, $name, $port = NULL) { $conn = $this->initHandler (); $conn->options (MYSQLI_OPT_LOCAL_INFILE, TRUE); $conn->options (MYSQLI_READ_DEFAULT_FILE, __DIR__.'/my.cnf'); $conn->real_connect ($host, $user, $pass, $name, $port); if (mysqli_connect_errno ()) { sleep (3); throw new Exception (mysqli_connect_errno (), mysqli_connect_error ()); return FALSE; } $this->isOpen = TRUE; $this->query ('SET CHARACTER SET utf8'); return TRUE; } /** * Closes the current connection, if it's closed does nothing. **/ function close () { if ($this->isOpen) { $this->conn->close (); $this->conn = NULL; } $this->isOpen = FALSE; } /** * Initializes the internal database connection handler. * * @return Objetct The connection handler **/ function initHandler () { if (!$this->conn) $this->conn = new \mysqli (); return $this->conn; } /** * Returns the internal database connection handler. This function shoud be * used to set options for specific databases that could not be set using * the Db\Conn class methods. * * @return Objetct The connection handler **/ function getHandler () { return $this->conn; } /** * Changes the default schema for the current connection. * * @param string $schema The schema name * @return boolean %TRUE if success, %FALSE otherwise **/ function selectDb ($dbName) { return $this->conn->select_db ($dbName); } /** * Executes the query and gets the result. * * @param string $query The SQL query * @param mixed[] $params The query parameters * * @return mixed The value or %NULL if error **/ function query ($query, $params = NULL) { $result = $this->conn->query ($this->render ($query, $params)); if (!$result) $this->checkError (); else while ($this->moreResults ()) $this->nextResult (); return $result; } /** * Checks whether the connection is open. * * @return boolean %TRUE if connection is open, %FALSE otherwise **/ function isOpen () { return $this->isOpen; } /** * Gets the first row value of the first column from a result. * * @param resource $result The database result * * @return mixed[] An associative array with the first row, %NULL if error **/ function getRowFromResult ($result) { if ($result) { $row = $result->fetch_assoc (); $result->free (); return $row; } return NULL; } /** * Gets the first row value of the first column from a result. * * @param resource $result The database result * * @return mixed The value or %NULL if error **/ function getValueFromResult ($result) { $value = NULL; if ($result) { $row = $result->fetch_row (); if ($row && count ($row) > 0) $value = $row[0]; $result->free (); } return $value; } /** * Executes the query and gets it's first row. * * @param string $query The SQL query * @param mixed[] $params The query parameters * * @return mixed[] An associative array with the first row, %NULL if error **/ function getRow ($query, $params = NULL) { $result = $this->query ($query, $params); return $this->getRowFromResult ($result); } /** * Executes the query and gets the first value of the first row. * * @param string $query The SQL query * @param mixed[] $params The query parameters * * @return mixed The value or %NULL if error **/ function getValue ($query, $params = NULL) { $result = $this->query ($query, $params); return $this->getValueFromResult ($result); } /** * Loads a query from a file and renders it. * * @param string $file The file path * @param mixed[] $params The query parameters * * @return mixed The query string **/ function loadFromFile ($file, $params = NULL) { $query = file_get_contents ($file .'.sql'); if ($query === FALSE) throw new Exception (NULL, 'Can not load query from file'); return $this->render ($query, $params); } /** * Executes the query stored in the specified file and gets the result. * * @param string $file The file path * @param mixed[] $params The query parameters * * @return mixed The value or %NULL if error **/ function queryFromFile ($file, $params = NULL) { $query = $this->loadFromFile ($file, $params); if ($query) return $this->query ($query); return NULL; } /** * Executes the file query and gets it's first row. * * @param string $file The file path * @param mixed[] $params The query parameters * * @return mixed[] An associative array with the first row, %NULL if error **/ function getRowFromFile ($file, $params = NULL) { $result = $this->queryFromFile ($file, $params); return $this->getRowFromResult ($result); } /** * Executes the file query and gets the first value of the first row. * * @param string $file The file path * @param mixed[] $params The query parameters * * @return mixed The value or %NULL if error **/ function getValueFromFile ($file, $params = NULL) { $result = $this->queryFromFile ($file, $params); return $this->getValueFromResult ($result); } /** * Execute multiple queries separated by semicolons. * * @param string $query The SQL query * @param mixed[] $params The query parameters * * @return mixed The value or %NULL if error **/ function multiQuery ($query, $params = NULL) { $success = $this->conn->multi_query ($this->render ($query, $params)); if (!$success) $this->checkError (); return $success; } /** * Prepare an SQL statement for execution. * * @param string $query The SQL query * * @return mixed The statement object or %FALSE if an error occurred **/ function prepare ($query) { return $this->conn->prepare ($query); } function storeResult () { $result = $this->conn->store_result (); if (!$result) $this->checkError (); return $result; } function moreResults () { return $this->conn->more_results (); } function nextResult () { $hasNext = $this->conn->next_result (); $this->checkError (); return $hasNext; } /** * Check if there has been an error in the last query or multiquery, * throwing a @Db\Exception exception if any. **/ function checkError () { if ($this->conn->errno) throw new Exception ($this->conn->errno, $this->conn->error); } /** * Check if there have been warnings in the last query. * * @return boolean %TRUE if there have been warnings %FALSE otherwise **/ function checkWarnings () { return $this->conn->warning_count > 0; } /** * Renders an SQL string using the given parameters. * * @param string $query The SQL string * @param mixed[] $paramsMap The query parameters * * @return string The rendered SQL string **/ function render ($query, $paramsMap = NULL) { if (isset ($paramsMap) && is_array ($paramsMap) && count ($paramsMap) > 0) { $i = 0; $params = []; foreach ($paramsMap as $key => $value) $params[$key] = $this->renderValue ($value); $replaceFunc = function ($matches) use (&$params, &$i) { $key = substr ($matches[0], 1); if (strlen ($key) == 0) $key = $i++; if (isset ($params[$key])) return $params[$key]; return '#'. $key; }; return preg_replace_callback ('/#\w*/', $replaceFunc, $query); } else return $query; } /** * Gets an SQL respresentation from a PHP value. * * @param mixed $value The value * * @return string The SQL value **/ function renderValue ($value) { if ($value !== NULL) switch (get_type ($value)) { case TYPE_BOOLEAN: return ($value) ? 'TRUE' : 'FALSE'; case TYPE_STRING: return '\'' . $this->conn->escape_string ($value) . '\''; case TYPE_DATE: return strftime ('\'%Y-%m-%d\'', $value->getTimestamp ()); case TYPE_TIME: return strftime ('\'%T\'', $value->getTimestamp ()); case TYPE_DATE_TIME: return strftime ('\'%Y-%m-%d %T\'', $value->getTimestamp ()); default: return '\'' . $this->conn->escape_string ($value) . '\''; } else return 'NULL'; } } ?>