MySQLi Wrapper: fetch_field() on a non-object - php

I'm using the following wrapper:
<?php
/**
* MysqliDb Class
*
* #category Database Access
* #package MysqliDb
* #author Jeffery Way <jeffrey#jeffrey-way.com>
* #author Josh Campbell <jcampbell#ajillion.com>
* #copyright Copyright (c) 2010
* #license http://opensource.org/licenses/gpl-3.0.html GNU Public License
* #version 1.1
**/
class MysqliDb
{
/**
* Static instance of self
*
* #var MysqliDb
*/
protected static $_instance;
/**
* MySQLi instance
*
* #var mysqli
*/
protected $_mysqli;
/**
* The SQL query to be prepared and executed
*
* #var string
*/
protected $_query;
/**
* An array that holds where conditions 'fieldname' => 'value'
*
* #var array
*/
protected $_where = array();
/**
* Dynamic type list for where condition values
*
* #var array
*/
protected $_whereTypeList;
/**
* Dynamic type list for table data values
*
* #var array
*/
protected $_paramTypeList;
/**
* Dynamic array that holds a combination of where condition/table data value types and parameter referances
*
* #var array
*/
protected $_bindParams = array(''); // Create the empty 0 index
/**
* #param string $host
* #param string $username
* #param string $password
* #param string $db
* #param int $port
*/
public function __construct($host, $username, $password, $db, $port = NULL)
{
if($port == NULL)
$port = ini_get('mysqli.default_port');
$this->_mysqli = new mysqli($host, $username, $password, $db, $port)
or die('There was a problem connecting to the database');
$this->_mysqli->set_charset('utf8');
self::$_instance = $this;
}
/**
* A method of returning the static instance to allow access to the
* instantiated object from within another class.
* Inheriting this class would require reloading connection info.
*
* #uses $db = MySqliDb::getInstance();
*
* #return object Returns the current instance.
*/
public static function getInstance()
{
return self::$_instance;
}
/**
* Reset states after an execution
*
* #return object Returns the current instance.
*/
protected function reset()
{
$this->_where = array();
$this->_bindParams = array(''); // Create the empty 0 index
unset($this->_query);
unset($this->_whereTypeList);
unset($this->_paramTypeList);
}
/**
* Pass in a raw query and an array containing the parameters to bind to the prepaird statement.
*
* #param string $query Contains a user-provided query.
* #param array $bindParams All variables to bind to the SQL statment.
*
* #return array Contains the returned rows from the query.
*/
public function rawQuery($query, $bindParams = null)
{
$this->_query = filter_var($query, FILTER_SANITIZE_STRING);
$stmt = $this->_prepareQuery();
if (is_array($bindParams) === true) {
$params = array(''); // Create the empty 0 index
foreach ($bindParams as $prop => $val) {
$params[0] .= $this->_determineType($val);
array_push($params, $bindParams[$prop]);
}
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($params));
}
$stmt->execute();
$this->reset();
return $this->_dynamicBindResults($stmt);
}
/**
*
* #param string $query Contains a user-provided select query.
* #param int $numRows The number of rows total to return.
*
* #return array Contains the returned rows from the query.
*/
public function query($query, $numRows = null)
{
$this->_query = filter_var($query, FILTER_SANITIZE_STRING);
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$this->reset();
return $this->_dynamicBindResults($stmt);
}
/**
* A convenient SELECT * function.
*
* #param string $tableName The name of the database table to work with.
* #param integer $numRows The number of rows total to return.
*
* #return array Contains the returned rows from the select query.
*/
public function get($tableName, $numRows = null)
{
$this->_query = "SELECT * FROM $tableName";
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$this->reset();
return $this->_dynamicBindResults($stmt);
}
/**
*
* #param <string $tableName The name of the table.
* #param array $insertData Data containing information for inserting into the DB.
*
* #return boolean Boolean indicating whether the insert query was completed succesfully.
*/
public function insert($tableName, $insertData)
{
$this->_query = "INSERT into $tableName";
$stmt = $this->_buildQuery(null, $insertData);
$stmt->execute();
$this->reset();
return ($stmt->affected_rows > 0 ? $stmt->insert_id : false);
}
/**
* Update query. Be sure to first call the "where" method.
*
* #param string $tableName The name of the database table to work with.
* #param array $tableData Array of data to update the desired row.
*
* #return boolean
*/
public function update($tableName, $tableData)
{
$this->_query = "UPDATE $tableName SET ";
$stmt = $this->_buildQuery(null, $tableData);
$stmt->execute();
$this->reset();
return ($stmt->affected_rows > 0);
}
/**
* Delete query. Call the "where" method first.
*
* #param string $tableName The name of the database table to work with.
* #param integer $numRows The number of rows to delete.
*
* #return boolean Indicates success. 0 or 1.
*/
public function delete($tableName, $numRows = null)
{
$this->_query = "DELETE FROM $tableName";
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$this->reset();
return ($stmt->affected_rows > 0);
}
/**
* This method allows you to specify multipl (method chaining optional) WHERE statements for SQL queries.
*
* #uses $MySqliDb->where('id', 7)->where('title', 'MyTitle');
*
* #param string $whereProp The name of the database field.
* #param mixed $whereValue The value of the database field.
*
* #return MysqliDb
*/
public function where($whereProp, $whereValue)
{
$this->_where[$whereProp] = $whereValue;
return $this;
}
/**
* This methods returns the ID of the last inserted item
*
* #return integer The last inserted item ID.
*/
public function getInsertId()
{
return $this->_mysqli->insert_id;
}
/**
* Escape harmful characters which might affect a query.
*
* #param string $str The string to escape.
*
* #return string The escaped string.
*/
public function escape($str)
{
return $this->_mysqli->real_escape_string($str);
}
/**
* This method is needed for prepared statements. They require
* the data type of the field to be bound with "i" s", etc.
* This function takes the input, determines what type it is,
* and then updates the param_type.
*
* #param mixed $item Input to determine the type.
*
* #return string The joined parameter types.
*/
protected function _determineType($item)
{
switch (gettype($item)) {
case 'NULL':
case 'string':
return 's';
break;
case 'integer':
return 'i';
break;
case 'blob':
return 'b';
break;
case 'double':
return 'd';
break;
}
return '';
}
/**
* Abstraction method that will compile the WHERE statement,
* any passed update data, and the desired rows.
* It then builds the SQL query.
*
* #param int $numRows The number of rows total to return.
* #param array $tableData Should contain an array of data for updating the database.
*
* #return mysqli_stmt Returns the $stmt object.
*/
protected function _buildQuery($numRows = null, $tableData = null)
{
$hasTableData = is_array($tableData);
$hasConditional = !empty($this->_where);
// Did the user call the "where" method?
if (!empty($this->_where)) {
// if update data was passed, filter through and create the SQL query, accordingly.
if ($hasTableData) {
$pos = strpos($this->_query, 'UPDATE');
if ($pos !== false) {
foreach ($tableData as $prop => $value) {
// determines what data type the item is, for binding purposes.
$this->_paramTypeList .= $this->_determineType($value);
// prepares the reset of the SQL query.
$this->_query .= ($prop . ' = ?, ');
}
$this->_query = rtrim($this->_query, ', ');
}
}
//Prepair the where portion of the query
$this->_query .= ' WHERE ';
foreach ($this->_where as $column => $value) {
// Determines what data type the where column is, for binding purposes.
$this->_whereTypeList .= $this->_determineType($value);
// Prepares the reset of the SQL query.
$this->_query .= ($column . ' = ? AND ');
}
$this->_query = rtrim($this->_query, ' AND ');
}
// Determine if is INSERT query
if ($hasTableData) {
$pos = strpos($this->_query, 'INSERT');
if ($pos !== false) {
//is insert statement
$keys = array_keys($tableData);
$values = array_values($tableData);
$num = count($keys);
// wrap values in quotes
foreach ($values as $key => $val) {
$values[$key] = "'{$val}'";
$this->_paramTypeList .= $this->_determineType($val);
}
$this->_query .= '(' . implode($keys, ', ') . ')';
$this->_query .= ' VALUES(';
while ($num !== 0) {
$this->_query .= '?, ';
$num--;
}
$this->_query = rtrim($this->_query, ', ');
$this->_query .= ')';
}
}
// Did the user set a limit
if (isset($numRows)) {
$this->_query .= ' LIMIT ' . (int)$numRows;
}
// Prepare query
$stmt = $this->_prepareQuery();
// Prepare table data bind parameters
if ($hasTableData) {
$this->_bindParams[0] = $this->_paramTypeList;
foreach ($tableData as $prop => $val) {
array_push($this->_bindParams, $tableData[$prop]);
}
}
// Prepare where condition bind parameters
if ($hasConditional) {
if ($this->_where) {
$this->_bindParams[0] .= $this->_whereTypeList;
foreach ($this->_where as $prop => $val) {
array_push($this->_bindParams, $this->_where[$prop]);
}
}
}
// Bind parameters to statment
if ($hasTableData || $hasConditional) {
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($this->_bindParams));
}
return $stmt;
}
/**
* This helper method takes care of prepared statements' "bind_result method
* , when the number of variables to pass is unknown.
*
* #param mysqli_stmt $stmt Equal to the prepared statement object.
*
* #return array The results of the SQL fetch.
*/
protected function _dynamicBindResults(mysqli_stmt $stmt)
{
$parameters = array();
$results = array();
$meta = $stmt->result_metadata();
$row = array();
while ($field = $meta->fetch_field()) {
$row[$field->name] = null;
$parameters[] = & $row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
$x = array();
foreach ($row as $key => $val) {
$x[$key] = $val;
}
array_push($results, $x);
}
return $results;
}
/**
* Method attempts to prepare the SQL query
* and throws an error if there was a problem.
*
* #return mysqli_stmt
*/
protected function _prepareQuery()
{
if (!$stmt = $this->_mysqli->prepare($this->_query)) {
trigger_error("Problem preparing query ($this->_query) " . $this->_mysqli->error, E_USER_ERROR);
}
return $stmt;
}
/**
* Close connection
*/
public function __destruct()
{
$this->_mysqli->close();
}
/**
* #param array $arr
*
* #return array
*/
protected function refValues($arr)
{
//Reference is required for PHP 5.3+
if (strnatcmp(phpversion(), '5.3') >= 0) {
$refs = array();
foreach ($arr as $key => $value) {
$refs[$key] = & $arr[$key];
}
return $refs;
}
return $arr;
}
} // END class
from this URL: https://github.com/ajillion/PHP-MySQLi-Database-Class.
I am using the rawQuery methode. It works fine for SELECT, but when I try to do an UPDATE, the following error shows up: Fatal error: Call to a member function fetch_field() on a non-object in ... on line 419 (that's the 7th line after function _dynamicBindResults). How is that possible?

UPDATE, INSERT, DELETE don't return results like a SELECT query does. Use the implemented update method for update queries:
$updateData = array(
'fieldOne' => 'fieldValue',
'fieldTwo' => 'fieldValue'
);
$db->where('id', int);
$results = $db->update('tableName', $updateData);

Related

How to solve error count php in my database class

I can not solve this problem, help me.
Warning: count(): Parameter must be an array or an object that
implements Countable in
/home/cabox/workspace/Datingmash/app/Classes/Database.php on line 74
The line 74:
public function bind($para, $value)
{
$this->parameters[count($this->parameters)] = ":" . $para . "\x7F" . utf8_encode($value);
}
This is the array
array(1) { [0]=> string(29) ":user_api_id1634508113362112" }
Full Code:
<?php
namespace App\Classes;
use PDO;
class Database extends DatabaseLogs {
private $pdo;
private $sQuery;
private $bConnected = false;
private $parameters;
public function __construct(){
$this->Connect();
$this->parameters = array();
}
private function Connect(){
$dsn = 'mysql:dbname='.APP_DATABASE_NAME.';host='.APP_DATABASE_HOSTNAME.'';
try {
$this->pdo = new PDO($dsn, APP_DATABASE_USERNAME, APP_DATABASE_PASSWORD, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->bConnected = true;
}
catch (PDOException $e) {
echo $this->ExceptionLog($e->getMessage());
die();
}
}
public function CloseConnection(){
$this->pdo = null;
}
private function Init($query,$parameters = "")
{
# Connect to database
if(!$this->bConnected) { $this->Connect(); }
try {
# Prepare query
$this->sQuery = $this->pdo->prepare($query);
# Add parameters to the parameter array
$this->bindMore($parameters);
# Bind parameters
if(!empty($this->parameters)) {
foreach($this->parameters as $param)
{
$parameters = explode("\x7F",$param);
$this->sQuery->bindParam($parameters[0],$parameters[1]);
}
}
# Execute SQL
$this->success = $this->sQuery->execute();
}
catch(PDOException $e)
{
# Write into log and display Exception
$this->ExceptionLog($e->getMessage(), $query );
}
# Reset the parameters
$this->parameters = array();
}
/**
* #void
*
* Add the parameter to the parameter array
* #param string $para
* #param string $value
*/
public function bind($para, $value)
{
$this->parameters[count($this->parameters)] = ":" . $para . "\x7F" . utf8_encode($value);
}
/**
* #void
*
* Add more parameters to the parameter array
* #param array $parray
*/
public function bindMore($parray)
{
if(empty($this->parameters) && is_array($parray)) {
$columns = array_keys($parray);
foreach($columns as $i => &$column) {
$this->bind($column, $parray[$column]);
}
}
}
/**
* If the SQL query contains a SELECT or SHOW statement it returns an array containing all of the result set row
* If the SQL statement is a DELETE, INSERT, or UPDATE statement it returns the number of affected rows
*
* #param string $query
* #param array $params
* #param int $fetchmode
* #return mixed
*/
public function query($query,$params = null, $fetchmode = PDO::FETCH_ASSOC)
{
$query = trim($query);
$this->Init($query,$params);
$rawStatement = explode(" ", $query);
# Which SQL statement is used
$statement = strtolower($rawStatement[0]);
if ($statement === 'select' || $statement === 'show') {
return $this->sQuery->fetchAll($fetchmode);
}
elseif ( $statement === 'insert' || $statement === 'update' || $statement === 'delete' ) {
return $this->sQuery->rowCount();
}
else {
return NULL;
}
}
/**
* Returns the last inserted id.
* #return string
*/
public function lastInsertId() {
return $this->pdo->lastInsertId();
}
/**
* Returns an array which represents a column from the result set
*
* #param string $query
* #param array $params
* #return array
*/
public function column($query,$params = null)
{
$this->Init($query,$params);
$Columns = $this->sQuery->fetchAll(PDO::FETCH_NUM);
$column = null;
foreach($Columns as $cells) {
$column[] = $cells[0];
}
return $column;
}
/**
* Returns an array which represents a row from the result set
*
* #param string $query
* #param array $params
* #param int $fetchmode
* #return array
*/
public function row($query,$params = null,$fetchmode = PDO::FETCH_ASSOC)
{
$this->Init($query,$params);
return $this->sQuery->fetch($fetchmode);
}
/**
* Returns the value of one single field/column
*
* #param string $query
* #param array $params
* #return string
*/
public function single($query,$params = null)
{
$this->Init($query,$params);
return $this->sQuery->fetchColumn();
}
/**
* Writes the log and returns the exception
*
* #param string $message
* #param string $sql
* #return string
*/
private function ExceptionLog($message , $sql = "")
{
$exception = 'Unhandled Exception. <br />';
$exception .= $message;
$exception .= "<br /> You can find the error back in the log.";
if(!empty($sql)) {
# Add the Raw SQL to the Log
$message .= "\r\nRaw SQL : " . $sql;
}
# Write into log
$this->log->write($message);
throw new Exception($message);
#return $exception;
}
}
?>
First of all, you don't need to pass count($this->paramters) as index,
The following code would just work if $this->paramters is an array
public function bind($para, $value)
{
$this->parameters[] = ":" . $para . "\x7F" . utf8_encode($value);
}
If you want to use it anyway, make sure $this->parameters is always an array or just fix it on the fly, use something like
public function bind($para, $value)
{
if(!is_array($this->parameters)){ $this->parameters = array(); }
$this->parameters[ count($this->parameters) ] = ":" . $para . "\x7F" . utf8_encode($value);
}

includes/MysqliDb.php on line 823 error - url shortener ads 1.3_2

* #author Josh Campbell
* #author Alexander V. Butenko
* #copyright Copyright (c) 2010
* #license http://opensource.org/licenses/gpl-3.0.html GNU Public License
* #version 2.0
/
class MysqliDb
{
/
* Static instance of self
*
* #var MysqliDb
*/
protected static $_instance;
/**
* Table prefix
*
* #var string
*/
protected static $_prefix;
/**
* MySQLi instance
*
* #var mysqli
*/
protected $_mysqli;
/**
* The SQL query to be prepared and executed
*
* #var string
*/
protected $_query;
/**
* The previously executed SQL query
*
* #var string
*/
protected $_lastQuery;
/**
* An array that holds where joins
*
* #var array
*/
protected $_join = array();
/**
* An array that holds where conditions 'fieldname' => 'value'
*
* #var array
*/
protected $_where = array();
/**
* Dynamic type list for order by condition value
*/
protected $_orderBy = array();
/**
* Dynamic type list for group by condition value
*/
protected $_groupBy = array();
/**
* Dynamic array that holds a combination of where condition/table data value types and parameter referances
*
* #var array
*/
protected $_bindParams = array(''); // Create the empty 0 index
/**
* Variable which holds an amount of returned rows during get/getOne/select queries
*
* #var string
*/
public $count = 0;
/**
* Variable which holds last statement error
*
* #var string
*/
protected $_stmtError;
/**
* Database credentials
*
* #var string
*/
protected $host;
protected $username;
protected $password;
protected $db;
protected $port;
/**
* Is Subquery object
*
*/
protected $isSubQuery = false;
/**
* #param string $host
* #param string $username
* #param string $password
* #param string $db
* #param int $port
*/
public function __construct($host = NULL, $username = NULL, $password = NULL, $db = NULL, $port = NULL)
{
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->db = $db;
if($port == NULL)
$this->port = ini_get ('mysqli.default_port');
else
$this->port = $port;
if ($host == null && $username == null && $db == null) {
$this->isSubQuery = true;
return;
}
// for subqueries we do not need database connection and redefine root instance
$this->connect();
$this->setPrefix();
self::$_instance = $this;
}
/**
* A method to connect to the database
*
*/
public function connect()
{
if ($this->isSubQuery)
return;
$this->_mysqli = new mysqli ($this->host, $this->username, $this->password, $this->db, $this->port)
or die('There was a problem connecting to the database');
$this->_mysqli->set_charset ('utf8');
}
/**
* A method of returning the static instance to allow access to the
* instantiated object from within another class.
* Inheriting this class would require reloading connection info.
*
* #uses $db = MySqliDb::getInstance();
*
* #return object Returns the current instance.
*/
public static function getInstance()
{
return self::$_instance;
}
/**
* Reset states after an execution
*
* #return object Returns the current instance.
*/
protected function reset()
{
$this->_where = array();
$this->_join = array();
$this->_orderBy = array();
$this->_groupBy = array();
$this->_bindParams = array(''); // Create the empty 0 index
$this->_query = null;
$this->count = 0;
}
/**
* Method to set a prefix
*
* #param string $prefix Contains a tableprefix
*/
public function setPrefix($prefix = '')
{
self::$_prefix = $prefix;
return $this;
}
/**
* Pass in a raw query and an array containing the parameters to bind to the prepaird statement.
*
* #param string $query Contains a user-provided query.
* #param array $bindParams All variables to bind to the SQL statment.
* #param bool $sanitize If query should be filtered before execution
*
* #return array Contains the returned rows from the query.
*/
public function rawQuery ($query, $bindParams = null, $sanitize = true)
{
$this->_query = $query;
if ($sanitize)
$this->_query = filter_var ($query, FILTER_SANITIZE_STRING,
FILTER_FLAG_NO_ENCODE_QUOTES);
$stmt = $this->_prepareQuery();
if (is_array($bindParams) === true) {
$params = array(''); // Create the empty 0 index
foreach ($bindParams as $prop => $val) {
$params[0] .= $this->_determineType($val);
array_push($params, $bindParams[$prop]);
}
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($params));
}
$stmt->execute();
$this->_stmtError = $stmt->error;
$this->reset();
return $this->_dynamicBindResults($stmt);
}
/**
*
* #param string $query Contains a user-provided select query.
* #param int $numRows The number of rows total to return.
*
* #return array Contains the returned rows from the query.
*/
public function query($query, $numRows = null)
{
$this->_query = filter_var($query, FILTER_SANITIZE_STRING);
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$this->_stmtError = $stmt->error;
$this->reset();
return $this->_dynamicBindResults($stmt);
}
/**
* A convenient SELECT * function.
*
* #param string $tableName The name of the database table to work with.
* #param integer $numRows The number of rows total to return.
*
* #return array Contains the returned rows from the select query.
*/
public function get($tableName, $numRows = null, $columns = '*')
{
if (empty ($columns))
$columns = '*';
$column = is_array($columns) ? implode(', ', $columns) : $columns;
$this->_query = "SELECT $column FROM " .self::$_prefix . $tableName;
$stmt = $this->_buildQuery($numRows);
if ($this->isSubQuery)
return $this;
$stmt->execute();
$this->_stmtError = $stmt->error;
$this->reset();
return $this->_dynamicBindResults($stmt);
}
/**
* A convenient SELECT * function to get one record.
*
* #param string $tableName The name of the database table to work with.
*
* #return array Contains the returned rows from the select query.
*/
public function getOne($tableName, $columns = '*')
{
$res = $this->get ($tableName, 1, $columns);
if (is_object($res))
return $res;
if (isset($res[0]))
return $res[0];
return null;
}
/**
*
* #param <string $tableName The name of the table.
* #param array $insertData Data containing information for inserting into the DB.
*
* #return boolean Boolean indicating whether the insert query was completed succesfully.
*/
public function insert($tableName, $insertData)
{
if ($this->isSubQuery)
return;
$this->_query = "INSERT into " .self::$_prefix . $tableName;
$stmt = $this->_buildQuery(null, $insertData);
$stmt->execute();
$this->_stmtError = $stmt->error;
$this->reset();
return ($stmt->affected_rows > 0 ? $stmt->insert_id : false);
}
/**
* Update query. Be sure to first call the "where" method.
*
* #param string $tableName The name of the database table to work with.
* #param array $tableData Array of data to update the desired row.
*
* #return boolean
*/
public function update($tableName, $tableData)
{
if ($this->isSubQuery)
return;
$this->_query = "UPDATE " . self::$_prefix . $tableName ." SET ";
$stmt = $this->_buildQuery (null, $tableData);
$status = $stmt->execute();
$this->reset();
$this->_stmtError = $stmt->error;
$this->count = $stmt->affected_rows;
return $status;
}
/**
* Delete query. Call the "where" method first.
*
* #param string $tableName The name of the database table to work with.
* #param integer $numRows The number of rows to delete.
*
* #return boolean Indicates success. 0 or 1.
*/
public function delete($tableName, $numRows = null)
{
if ($this->isSubQuery)
return;
$this->_query = "DELETE FROM " . self::$_prefix . $tableName;
$stmt = $this->_buildQuery($numRows);
$stmt->execute();
$this->_stmtError = $stmt->error;
$this->reset();
return ($stmt->affected_rows > 0);
}
/**
* This method allows you to specify multiple (method chaining optional) AND WHERE statements for SQL queries.
*
* #uses $MySqliDb->where('id', 7)->where('title', 'MyTitle');
*
* #param string $whereProp The name of the database field.
* #param mixed $whereValue The value of the database field.
*
* #return MysqliDb
*/
public function where($whereProp, $whereValue = null, $operator = null)
{
if ($operator)
$whereValue = Array ($operator => $whereValue);
$this->_where[] = Array ("AND", $whereValue, $whereProp);
return $this;
}
/**
* This method allows you to specify multiple (method chaining optional) OR WHERE statements for SQL queries.
*
* #uses $MySqliDb->orWhere('id', 7)->orWhere('title', 'MyTitle');
*
* #param string $whereProp The name of the database field.
* #param mixed $whereValue The value of the database field.
*
* #return MysqliDb
*/
public function orWhere($whereProp, $whereValue = null, $operator = null)
{
if ($operator)
$whereValue = Array ($operator => $whereValue);
$this->_where[] = Array ("OR", $whereValue, $whereProp);
return $this;
}
/**
* This method allows you to concatenate joins for the final SQL statement.
*
* #uses $MySqliDb->join('table1', 'field1 <> field2', 'LEFT')
*
* #param string $joinTable The name of the table.
* #param string $joinCondition the condition.
* #param string $joinType 'LEFT', 'INNER' etc.
*
* #return MysqliDb
*/
public function join($joinTable, $joinCondition, $joinType = '')
{
$allowedTypes = array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER');
$joinType = strtoupper (trim ($joinType));
$joinTable = filter_var($joinTable, FILTER_SANITIZE_STRING);
if ($joinType && !in_array ($joinType, $allowedTypes))
die ('Wrong JOIN type: '.$joinType);
$this->_join[$joinType . " JOIN " . self::$_prefix . $joinTable] = $joinCondition;
return $this;
}
/**
* This method allows you to specify multiple (method chaining optional) ORDER BY statements for SQL queries.
*
* #uses $MySqliDb->orderBy('id', 'desc')->orderBy('name', 'desc');
*
* #param string $orderByField The name of the database field.
* #param string $orderByDirection Order direction.
*
* #return MysqliDb
*/
public function orderBy($orderByField, $orderbyDirection = "DESC")
{
$allowedDirection = Array ("ASC", "DESC");
$orderbyDirection = strtoupper (trim ($orderbyDirection));
$orderByField = preg_replace ("/[^-a-z0-9\.\(\),_]+/i",'', $orderByField);
if (empty($orderbyDirection) || !in_array ($orderbyDirection, $allowedDirection))
die ('Wrong order direction: '.$orderbyDirection);
$this->_orderBy[$orderByField] = $orderbyDirection;
return $this;
}
/**
* This method allows you to specify multiple (method chaining optional) GROUP BY statements for SQL queries.
*
* #uses $MySqliDb->groupBy('name');
*
* #param string $groupByField The name of the database field.
*
* #return MysqliDb
*/
public function groupBy($groupByField)
{
$groupByField = preg_replace ("/[^-a-z0-9\.\(\),_]+/i",'', $groupByField);
$this->_groupBy[] = $groupByField;
return $this;
}
/**
* This methods returns the ID of the last inserted item
*
* #return integer The last inserted item ID.
*/
public function getInsertId()
{
return $this->_mysqli->insert_id;
}
/**
* Escape harmful characters which might affect a query.
*
* #param string $str The string to escape.
*
* #return string The escaped string.
*/
public function escape($str)
{
return $this->_mysqli->real_escape_string($str);
}
/**
* Method to call mysqli->ping() to keep unused connections open on
* long-running scripts, or to reconnect timed out connections (if php.ini has
* global mysqli.reconnect set to true). Can't do this directly using object
* since _mysqli is protected.
*
* #return bool True if connection is up
*/
public function ping() {
return $this->_mysqli->ping();
}
/**
* This method is needed for prepared statements. They require
* the data type of the field to be bound with "i" s", etc.
* This function takes the input, determines what type it is,
* and then updates the param_type.
*
* #param mixed $item Input to determine the type.
*
* #return string The joined parameter types.
*/
protected function _determineType($item)
{
switch (gettype($item)) {
case 'NULL':
case 'string':
return 's';
break;
case 'boolean':
case 'integer':
return 'i';
break;
case 'blob':
return 'b';
break;
case 'double':
return 'd';
break;
}
return '';
}
/**
* Helper function to add variables into bind parameters array
*
* #param string Variable value
*/
protected function _bindParam($value) {
$this->_bindParams[0] .= $this->_determineType ($value);
array_push ($this->_bindParams, $value);
}
/**
* Helper function to add variables into bind parameters array in bulk
*
* #param Array Variable with values
*/
protected function _bindParams ($values) {
foreach ($values as $value)
$this->_bindParam ($value);
}
/**
* Helper function to add variables into bind parameters array and will return
* its SQL part of the query according to operator in ' $operator ?' or
* ' $operator ($subquery) ' formats
*
* #param Array Variable with values
*/
protected function _buildPair ($operator, $value) {
if (!is_object($value)) {
$this->_bindParam ($value);
return ' ' . $operator. ' ? ';
}
$subQuery = $value->getSubQuery ();
$this->_bindParams ($subQuery['params']);
return " " . $operator . " (" . $subQuery['query'] . ")";
}
/**
* Abstraction method that will compile the WHERE statement,
* any passed update data, and the desired rows.
* It then builds the SQL query.
*
* #param int $numRows The number of rows total to return.
* #param array $tableData Should contain an array of data for updating the database.
*
* #return mysqli_stmt Returns the $stmt object.
*/
protected function _buildQuery($numRows = null, $tableData = null)
{
$this->_buildJoin();
$this->_buildTableData ($tableData);
$this->_buildWhere();
$this->_buildGroupBy();
$this->_buildOrderBy();
$this->_buildLimit ($numRows);
$this->_lastQuery = $this->replacePlaceHolders ($this->_query, $this->_bindParams);
if ($this->isSubQuery)
return;
// Prepare query
$stmt = $this->_prepareQuery();
// Bind parameters to statement if any
if (count ($this->_bindParams) > 1)
call_user_func_array(array($stmt, 'bind_param'), $this->refValues($this->_bindParams));
return $stmt;
}
/**
* This helper method takes care of prepared statements' "bind_result method
* , when the number of variables to pass is unknown.
*
* #param mysqli_stmt $stmt Equal to the prepared statement object.
*
* #return array The results of the SQL fetch.
*/
protected function _dynamicBindResults(mysqli_stmt $stmt)
{
$parameters = array();
$results = array();
$meta = $stmt->result_metadata();
// if $meta is false yet sqlstate is true, there's no sql error but the query is
// most likely an update/insert/delete which doesn't produce any results
if(!$meta && $stmt->sqlstate) {
return array();
}
$row = array();
while ($field = $meta->fetch_field()) {
$row[$field->name] = null;
$parameters[] = & $row[$field->name];
}
// avoid out of memory bug in php 5.2 and 5.3
// https://github.com/joshcam/PHP-MySQLi-Database-Class/pull/119
if (version_compare (phpversion(), '5.4', '<'))
$stmt->store_result();
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
$x = array();
foreach ($row as $key => $val) {
$x[$key] = $val;
}
$this->count++;
array_push($results, $x);
}
return $results;
}
/**
* Abstraction method that will build an JOIN part of the query
*/
protected function _buildJoin () {
if (empty ($this->_join))
return;
foreach ($this->_join as $prop => $value)
$this->_query .= " " . $prop . " on " . $value;
}
/**
* Abstraction method that will build an INSERT or UPDATE part of the query
*/
protected function _buildTableData ($tableData) {
if (!is_array ($tableData))
return;
$isInsert = strpos ($this->_query, 'INSERT');
$isUpdate = strpos ($this->_query, 'UPDATE');
if ($isInsert !== false) {
$this->_query .= '(`' . implode(array_keys($tableData), '`, `') . '`)';
$this->_query .= ' VALUES(';
}
foreach ($tableData as $column => $value) {
if ($isUpdate !== false)
$this->_query .= "`" . $column . "` = ";
// Subquery value
if (is_object ($value)) {
$this->_query .= $this->_buildPair ("", $value) . ", ";
continue;
}
// Simple value
if (!is_array ($value)) {
$this->_bindParam ($value);
$this->_query .= '?, ';
continue;
}
// Function value
$key = key ($value);
$val = $value[$key];
switch ($key) {
case '[I]':
$this->_query .= $column . $val . ", ";
break;
case '[F]':
$this->_query .= $val[0] . ", ";
if (!empty ($val[1]))
$this->_bindParams ($val[1]);
break;
case '[N]':
if ($val == null)
$this->_query .= "!" . $column . ", ";
else
$this->_query .= "!" . $val . ", ";
break;
default:
die ("Wrong operation");
}
}
$this->_query = rtrim($this->_query, ', ');
if ($isInsert !== false)
$this->_query .= ')';
}
/**
* Abstraction method that will build the part of the WHERE conditions
*/
protected function _buildWhere () {
if (empty ($this->_where))
return;
//Prepair the where portion of the query
$this->_query .= ' WHERE ';
// Remove first AND/OR concatenator
$this->_where[0][0] = '';
foreach ($this->_where as $cond) {
list ($concat, $wValue, $wKey) = $cond;
$this->_query .= " " . $concat ." " . $wKey;
// Empty value (raw where condition in wKey)
if ($wValue === null)
continue;
// Simple = comparison
if (!is_array ($wValue))
$wValue = Array ('=' => $wValue);
$key = key ($wValue);
$val = $wValue[$key];
switch (strtolower ($key)) {
case '0':
$this->_bindParams ($wValue);
break;
case 'not in':
case 'in':
$comparison = ' ' . $key . ' (';
if (is_object ($val)) {
$comparison .= $this->_buildPair ("", $val);
} else {
foreach ($val as $v) {
$comparison .= ' ?,';
$this->_bindParam ($v);
}
}
$this->_query .= rtrim($comparison, ',').' ) ';
break;
case 'not between':
case 'between':
$this->_query .= " $key ? AND ? ";
$this->_bindParams ($val);
break;
default:
$this->_query .= $this->_buildPair ($key, $val);
}
}
}
/**
* Abstraction method that will build the GROUP BY part of the WHERE statement
*
*/
protected function _buildGroupBy () {
if (empty ($this->_groupBy))
return;
$this->_query .= " GROUP BY ";
foreach ($this->_groupBy as $key => $value)
$this->_query .= $value . ", ";
$this->_query = rtrim($this->_query, ', ') . " ";
}
/**
* Abstraction method that will build the LIMIT part of the WHERE statement
*
* #param int $numRows The number of rows total to return.
*/
protected function _buildOrderBy () {
if (empty ($this->_orderBy))
return;
$this->_query .= " ORDER BY ";
foreach ($this->_orderBy as $prop => $value)
$this->_query .= $prop . " " . $value . ", ";
$this->_query = rtrim ($this->_query, ', ') . " ";
}
/**
* Abstraction method that will build the LIMIT part of the WHERE statement
*
* #param int $numRows The number of rows total to return.
*/
protected function _buildLimit ($numRows) {
if (!isset ($numRows))
return;
if (is_array ($numRows))
$this->_query .= ' LIMIT ' . (int)$numRows[0] . ', ' . (int)$numRows[1];
else
$this->_query .= ' LIMIT ' . (int)$numRows;
}
/**
* Method attempts to prepare the SQL query
* and throws an error if there was a problem.
*
* #return mysqli_stmt
*/
protected function _prepareQuery()
{
if (!$stmt = $this->_mysqli->prepare($this->_query)) {
trigger_error("Problem preparing query ($this->_query) " . $this->_mysqli->error, E_USER_ERROR);
}
return $stmt;
}
/**
* Close connection
*/
public function __destruct()
{
if (!$this->isSubQuery)
return;
if ($this->_mysqli)
$this->_mysqli->close();
}
/**
* #param array $arr
*
* #return array
*/
protected function refValues($arr)
{
//Reference is required for PHP 5.3+
if (strnatcmp(phpversion(), '5.3') >= 0) {
$refs = array();
foreach ($arr as $key => $value) {
$refs[$key] = & $arr[$key];
}
return $refs;
}
return $arr;
}
/**
* Function to replace ? with variables from bind variable
* #param string $str
* #param Array $vals
*
* #return string
*/
protected function replacePlaceHolders ($str, $vals) {
$i = 1;
$newStr = "";
while ($pos = strpos ($str, "?")) {
$val = $vals[$i++];
if (is_object ($val))
$val = '[object]';
$newStr .= substr ($str, 0, $pos) . $val;
$str = substr ($str, $pos + 1);
}
return $newStr;
}
/**
* Method returns last executed query
*
* #return string
*/
public function getLastQuery () {
return $this->_lastQuery;
}
/**
* Method returns mysql error
*
* #return string
*/
public function getLastError () {
return $this->_stmtError . " " . $this->_mysqli->error;
}
/**
* Mostly internal method to get query and its params out of subquery object
* after get() and getAll()
*
* #return array
*/
public function getSubQuery () {
if (!$this->isSubQuery)
return null;
array_shift ($this->_bindParams);
$val = Array ('query' => $this->_query,
'params' => $this->_bindParams
);
$this->reset();
return $val;
}
/* Helper functions */
/**
* Method returns generated interval function as a string
*
* #param string interval in the formats:
* "1", "-1d" or "- 1 day" -- For interval - 1 day
* Supported intervals [s]econd, [m]inute, [h]hour, [d]day, [M]onth, [Y]ear
* Default null;
* #param string Initial date
*
* #return string
*/
public function interval ($diff, $func = "NOW()") {
$types = Array ("s" => "second", "m" => "minute", "h" => "hour", "d" => "day", "M" => "month", "Y" => "year");
$incr = '+';
$items = '';
$type = 'd';
if ($diff && preg_match('/([+-]?) ?([0-9]+) ?([a-zA-Z]?)/',$diff, $matches)) {
if (!empty ($matches[1])) $incr = $matches[1];
if (!empty ($matches[2])) $items = $matches[2];
if (!empty ($matches[3])) $type = $matches[3];
if (!in_array($type, array_keys($types)))
trigger_error ("invalid interval type in '{$diff}'");
$func .= " ".$incr ." interval ". $items ." ".$types[$type] . " ";
}
return $func;
}
/**
* Method returns generated interval function as an insert/update function
*
* #param string interval in the formats:
* "1", "-1d" or "- 1 day" -- For interval - 1 day
* Supported intervals [s]econd, [m]inute, [h]hour, [d]day,
[M]onth, [Y]ear
* Default null;
* #param string Initial date
*
* #return array
*/
public function now ($diff = null, $func = "NOW()") {
return Array ("[F]" => Array($this->interval($diff, $func)));
}
/**
* Method generates incremental function call
* #param int increment amount. 1 by default
*/
public function inc($num = 1) {
return Array ("[I]" => "+" . (int)$num);
}
/**
* Method generates decrimental function call
* #param int increment amount. 1 by default
*/
public function dec ($num = 1) {
return Array ("[I]" => "-" . (int)$num);
}
/**
* Method generates change boolean function call
* #param string column name. null by default
*/
public function not ($col = null) {
return Array ("[N]" => (string)$col);
}
/**
* Method generates user defined function call
* #param string user function body
*/
public function func ($expr, $bindParams = null) {
return Array ("[F]" => Array($expr, $bindParams));
}
/**
* Method creates new mysqlidb object for a subquery generation
*/
public static function subQuery()
{
return new MysqliDb();
}
/**
* Method returns a copy of a mysqlidb subquery object
*
* #param object new mysqlidb object
*/
public function copy ()
{
return clone $this;
}
/**
* Begin a transaction
*
* #uses mysqli->autocommit(false)
* #uses register_shutdown_function(array($this, "_transaction_shutdown_check"))
*/
public function startTransaction () {
$this->_mysqli->autocommit (false);
$this->_transaction_in_progress = true;
register_shutdown_function (array ($this, "_transaction_status_check"));
}
/**
* Transaction commit
*
* #uses mysqli->commit();
* #uses mysqli->autocommit(true);
*/
public function commit () {
$this->_mysqli->commit ();
$this->_transaction_in_progress = false;
$this->_mysqli->autocommit (true);
}
/**
* Transaction rollback function
*
* #uses mysqli->rollback();
* #uses mysqli->autocommit(true);
*/
public function rollback () {
$this->_mysqli->rollback ();
$this->_transaction_in_progress = false;
$this->_mysqli->autocommit (true);
}
/**
* Shutdown handler to rollback uncommited operations in order to keep
* atomic operations sane.
*
* #uses mysqli->rollback();
*/
public function _transaction_status_check () {
if (!$this->_transaction_in_progress)
return;
$this->rollback ();
}
} // END class

Query in a class with variable

I have created a timeclock system for a website admin area I am working on. But I want to use a class to handle the code in a better way so I am starting over. So far I have 2 classes. One to handle the database connection and the queries to the database through PDO.
When starting the class for the timeclock (Which I am having to build from scratch) I am getting close because I am no longer receiving errors when I load the page. But the results of the query are not right as I should be returning "true" instead of NULL for a record coming from the database. Can someone please help me understand what I am doing wrong.
My Database class is like so(From GitHub)...
/**
* DB - A simple database class
*
* #author Author: Vivek Wicky Aswal. (https://twitter.com/#!/VivekWickyAswal)
* #git https://github.com/indieteq/PHP-MySQL-PDO-Database-Class
* #version 0.2ab
*
*/
require("Log.class.php");
class DB
{
# #object, The PDO object
private $pdo;
# #object, PDO statement object
private $sQuery;
# #array, The database settings
private $settings;
# #bool , Connected to the database
private $bConnected = false;
# #object, Object for logging exceptions
private $log;
# #array, The parameters of the SQL query
private $parameters;
/**
* Default Constructor
*
* 1. Instantiate Log class.
* 2. Connect to database.
* 3. Creates the parameter array.
*/
public function __construct()
{
$this->log = new Log();
$this->Connect();
$this->parameters = array();
}
/**
* This method makes connection to the database.
*
* 1. Reads the database settings from a ini file.
* 2. Puts the ini content into the settings array.
* 3. Tries to connect to the database.
* 4. If connection failed, exception is displayed and a log file gets created.
*/
private function Connect()
{
$host = 'localhost';
$username = 'root';
$password = '';
$dbname = 'acro_1986';
//$this->settings = parse_ini_file("settings.ini.php");
$dsn = 'mysql:dbname='.$dbname.';host='.$host.'';
try
{
# Read settings from INI file, set UTF8
$this->pdo = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
# We can now log any exceptions on Fatal error.
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
# Disable emulation of prepared statements, use REAL prepared statements instead.
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
# Connection succeeded, set the boolean to true.
$this->bConnected = true;
}
catch (PDOException $e)
{
# Write into log
echo $this->ExceptionLog($e->getMessage());
die();
}
}
/*
* You can use this little method if you want to close the PDO connection
*
*/
public function CloseConnection()
{
# Set the PDO object to null to close the connection
# http://www.php.net/manual/en/pdo.connections.php
$this->pdo = null;
}
/**
* Every method which needs to execute a SQL query uses this method.
*
* 1. If not connected, connect to the database.
* 2. Prepare Query.
* 3. Parameterize Query.
* 4. Execute Query.
* 5. On exception : Write Exception into the log + SQL query.
* 6. Reset the Parameters.
*/
private function Init($query,$parameters = "")
{
# Connect to database
if(!$this->bConnected) { $this->Connect(); }
try {
# Prepare query
$this->sQuery = $this->pdo->prepare($query);
# Add parameters to the parameter array
$this->bindMore($parameters);
# Bind parameters
if(!empty($this->parameters)) {
foreach($this->parameters as $param)
{
$parameters = explode("\x7F",$param);
$this->sQuery->bindParam($parameters[0],$parameters[1]);
}
}
# Execute SQL
$this->succes = $this->sQuery->execute();
}
catch(PDOException $e)
{
# Write into log and display Exception
echo $this->ExceptionLog($e->getMessage(), $query );
die();
}
# Reset the parameters
$this->parameters = array();
}
/**
* #void
*
* Add the parameter to the parameter array
* #param string $para
* #param string $value
*/
public function bind($para, $value)
{
$this->parameters[sizeof($this->parameters)] = ":" . $para . "\x7F" . utf8_encode($value);
}
/**
* #void
*
* Add more parameters to the parameter array
* #param array $parray
*/
public function bindMore($parray)
{
if(empty($this->parameters) && is_array($parray)) {
$columns = array_keys($parray);
foreach($columns as $i => &$column) {
$this->bind($column, $parray[$column]);
}
}
}
/**
* If the SQL query contains a SELECT or SHOW statement it returns an array containing all of the result set row
* If the SQL statement is a DELETE, INSERT, or UPDATE statement it returns the number of affected rows
*
* #param string $query
* #param array $params
* #param int $fetchmode
* #return mixed
*/
public function query($query,$params = null, $fetchmode = PDO::FETCH_ASSOC)
{
$query = trim($query);
$this->Init($query,$params);
$rawStatement = explode(" ", $query);
# Which SQL statement is used
$statement = strtolower($rawStatement[0]);
if ($statement === 'select' || $statement === 'show') {
return $this->sQuery->fetchAll($fetchmode);
}
elseif ( $statement === 'insert' || $statement === 'update' || $statement === 'delete' ) {
return $this->sQuery->rowCount();
}
else {
return NULL;
}
}
/**
* Returns the last inserted id.
* #return string
*/
public function lastInsertId() {
return $this->pdo->lastInsertId();
}
/**
* Returns an array which represents a column from the result set
*
* #param string $query
* #param array $params
* #return array
*/
public function column($query,$params = null)
{
$this->Init($query,$params);
$Columns = $this->sQuery->fetchAll(PDO::FETCH_NUM);
$column = null;
foreach($Columns as $cells) {
$column[] = $cells[0];
}
return $column;
}
/**
* Returns an array which represents a row from the result set
*
* #param string $query
* #param array $params
* #param int $fetchmode
* #return array
*/
public function row($query,$params = null,$fetchmode = PDO::FETCH_ASSOC)
{
$this->Init($query,$params);
return $this->sQuery->fetch($fetchmode);
}
/**
* Returns the value of one single field/column
*
* #param string $query
* #param array $params
* #return string
*/
public function single($query,$params = null)
{
$this->Init($query,$params);
return $this->sQuery->fetchColumn();
}
/**
* Writes the log and returns the exception
*
* #param string $message
* #param string $sql
* #return string
*/
private function ExceptionLog($message , $sql = "")
{
$exception = 'Unhandled Exception. <br />';
$exception .= $message;
$exception .= "<br /> You can find the error back in the log.";
if(!empty($sql)) {
# Add the Raw SQL to the Log
$message .= "\r\nRaw SQL : " . $sql;
}
# Write into log
$this->log->write($message);
return $exception;
}
}
My Timeclock class...
class Timeclock {
public $user_id;
public function __construct($user_id) {
$this->user_id = $user_id ;
$this->db = new Db();
//$this->clocked_in = is_user_clocked_in($user_id);
}
public function is_user_clocked_in(){
$result = $this->db->query("SELECT * FROM timeclock WHERE user_id = :user_id AND time_out IS NULL", array("user_id"=>$this->user_id));
if ( count ( $result ) > 0 ){
return $result[0];
}else{
return null;
}
}
}
And I am calling it like so...
if (isset($_SESSION['admin'])) {
$_user_id = $_SESSION['admin'][0]['user_id'];
// calls action and determines case
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else if (isset($_GET['action'])) {
$action = $_GET['action'];
} else {
$action = 'home';
}
$action = strtolower($action);
switch ($action) {
case 'home':
$timeclock = new Timeclock($_user_id);
$user = new Timeclock($timeclock->user_id);
$clocked_in = $user->is_user_clocked_in();
include ('dashboard.php');
break;
}
}
Also, is it possible to have every function in the class (Once its done) run one after the other and fill in the declared variables at the top (Once I have added them of course) so I can just call the class and have it run through once? Or will I have to call each function individually on demand?
Thanks for the attempt to help #Ohgodwhy. $clocked_in was returning an array because I asked it to select all columns in the table. So when there was a result, it was an array. I changed the return of the function to return true instead of $result[0] because I only need to know if the user is logged in. I could have probably just changed the query to select that column as well. After doing that, it worked great until I provided a value for the table field (Making the user clocked_in). I then got a Undefined offset:0 error because I was trying to call the value of $result[0] when there was no array indexed because the query obviously returns array(0); I just changed the count to check to see if $result exists.
updated code is as follows in case someone comes across this
Timeclock Class
class Timeclock {
public $user_id;
public function __construct($user_id) {
$this->user_id = $user_id ;
$this->db = new Db();
//$this->clocked_in = is_user_clocked_in($user_id);
}
public function is_user_clocked_in(){
$result = $this->db->query("SELECT * FROM timeclock WHERE user_id = :user_id AND time_out IS NULL", array("user_id"=>$this->user_id));
if ( count ($result) > 0 ){
return true;
}else{
return null;
}
}
}

Extend MySQLi Class PHP

I have downloaded the SafeMySQL class which I will post below. I would like to extend this database class to all of my other classes throughout the site that call queries. Currently, I have the main db connector set as a global variable, but I have to call it inside each class constructor and all of the class's methods. Surely there has to be an easier way?
Here is the DB class:
class SafeMySQL
{
private $conn;
private $stats;
private $emode;
private $exname;
private $defaults = array(
'host' => 'localhost',
'user' => '',
'pass' => '',
'db' => '',
'port' => NULL,
'socket' => NULL,
'pconnect' => FALSE,
'charset' => 'utf8',
'errmode' => 'error', //or exception
'exception' => 'Exception', //Exception class name
);
const RESULT_ASSOC = MYSQLI_ASSOC;
const RESULT_NUM = MYSQLI_NUM;
public function __construct($opt = array())
{
$opt = array_merge($this->defaults,$opt);
$this->emode = $opt['errmode'];
$this->exname = $opt['exception'];
if ($opt['pconnect'])
{
$opt['host'] = "p:".$opt['host'];
}
#$this->conn = mysqli_connect($opt['host'], $opt['user'], $opt['pass'], $opt['db'], $opt['port'], $opt['socket']);
if ( !$this->conn )
{
$this->error(mysqli_connect_errno()." ".mysqli_connect_error());
}
mysqli_set_charset($this->conn, $opt['charset']) or $this->error(mysqli_error($this->conn));
unset($opt); // I am paranoid
}
/**
* Conventional function to run a query with placeholders. A mysqli_query wrapper with placeholders support
*
* Examples:
* $db->query("DELETE FROM table WHERE id=?i", $id);
*
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return resource|FALSE whatever mysqli_query returns
*/
public function query()
{
return $this->rawQuery($this->prepareQuery(func_get_args()));
}
/**
* Conventional function to fetch single row.
*
* #param resource $result - myqli result
* #param int $mode - optional fetch mode, RESULT_ASSOC|RESULT_NUM, default RESULT_ASSOC
* #return array|FALSE whatever mysqli_fetch_array returns
*/
public function fetch($result,$mode=self::RESULT_ASSOC)
{
return mysqli_fetch_array($result, $mode);
}
/**
* Conventional function to get number of affected rows.
*
* #return int whatever mysqli_affected_rows returns
*/
public function affectedRows()
{
return mysqli_affected_rows ($this->conn);
}
/**
* Conventional function to get last insert id.
*
* #return int whatever mysqli_insert_id returns
*/
public function insertId()
{
return mysqli_insert_id($this->conn);
}
/**
* Conventional function to get number of rows in the resultset.
*
* #param resource $result - myqli result
* #return int whatever mysqli_num_rows returns
*/
public function numRows($result)
{
return mysqli_num_rows($result);
}
/**
* Conventional function to free the resultset.
*/
public function free($result)
{
mysqli_free_result($result);
}
/**
* Helper function to get scalar value right out of query and optional arguments
*
* Examples:
* $name = $db->getOne("SELECT name FROM table WHERE id=1");
* $name = $db->getOne("SELECT name FROM table WHERE id=?i", $id);
*
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return string|FALSE either first column of the first row of resultset or FALSE if none found
*/
public function getOne()
{
$query = $this->prepareQuery(func_get_args());
if ($res = $this->rawQuery($query))
{
$row = $this->fetch($res);
if (is_array($row)) {
return reset($row);
}
$this->free($res);
}
return FALSE;
}
/**
* Helper function to get single row right out of query and optional arguments
*
* Examples:
* $data = $db->getRow("SELECT * FROM table WHERE id=1");
* $data = $db->getOne("SELECT * FROM table WHERE id=?i", $id);
*
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return array|FALSE either associative array contains first row of resultset or FALSE if none found
*/
public function getRow()
{
$query = $this->prepareQuery(func_get_args());
if ($res = $this->rawQuery($query)) {
$ret = $this->fetch($res);
$this->free($res);
return $ret;
}
return FALSE;
}
/**
* Helper function to get single column right out of query and optional arguments
*
* Examples:
* $ids = $db->getCol("SELECT id FROM table WHERE cat=1");
* $ids = $db->getCol("SELECT id FROM tags WHERE tagname = ?s", $tag);
*
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return array|FALSE either enumerated array of first fields of all rows of resultset or FALSE if none found
*/
public function getCol()
{
$ret = array();
$query = $this->prepareQuery(func_get_args());
if ( $res = $this->rawQuery($query) )
{
while($row = $this->fetch($res))
{
$ret[] = reset($row);
}
$this->free($res);
}
return $ret;
}
/**
* Helper function to get all the rows of resultset right out of query and optional arguments
*
* Examples:
* $data = $db->getAll("SELECT * FROM table");
* $data = $db->getAll("SELECT * FROM table LIMIT ?i,?i", $start, $rows);
*
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return array enumerated 2d array contains the resultset. Empty if no rows found.
*/
public function getAll()
{
$ret = array();
$query = $this->prepareQuery(func_get_args());
if ( $res = $this->rawQuery($query) )
{
while($row = $this->fetch($res))
{
$ret[] = $row;
}
$this->free($res);
}
return $ret;
}
/**
* Helper function to get all the rows of resultset into indexed array right out of query and optional arguments
*
* Examples:
* $data = $db->getInd("id", "SELECT * FROM table");
* $data = $db->getInd("id", "SELECT * FROM table LIMIT ?i,?i", $start, $rows);
*
* #param string $index - name of the field which value is used to index resulting array
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return array - associative 2d array contains the resultset. Empty if no rows found.
*/
public function getInd()
{
$args = func_get_args();
$index = array_shift($args);
$query = $this->prepareQuery($args);
$ret = array();
if ( $res = $this->rawQuery($query) )
{
while($row = $this->fetch($res))
{
$ret[$row[$index]] = $row;
}
$this->free($res);
}
return $ret;
}
/**
* Helper function to get a dictionary-style array right out of query and optional arguments
*
* Examples:
* $data = $db->getIndCol("name", "SELECT name, id FROM cities");
*
* #param string $index - name of the field which value is used to index resulting array
* #param string $query - an SQL query with placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the query
* #return array - associative array contains key=value pairs out of resultset. Empty if no rows found.
*/
public function getIndCol()
{
$args = func_get_args();
$index = array_shift($args);
$query = $this->prepareQuery($args);
$ret = array();
if ( $res = $this->rawQuery($query) )
{
while($row = $this->fetch($res))
{
$key = $row[$index];
unset($row[$index]);
$ret[$key] = reset($row);
}
$this->free($res);
}
return $ret;
}
/**
* Function to parse placeholders either in the full query or a query part
* unlike native prepared statements, allows ANY query part to be parsed
*
* useful for debug
* and EXTREMELY useful for conditional query building
* like adding various query parts using loops, conditions, etc.
* already parsed parts have to be added via ?p placeholder
*
* Examples:
* $query = $db->parse("SELECT * FROM table WHERE foo=?s AND bar=?s", $foo, $bar);
* echo $query;
*
* if ($foo) {
* $qpart = $db->parse(" AND foo=?s", $foo);
* }
* $data = $db->getAll("SELECT * FROM table WHERE bar=?s ?p", $bar, $qpart);
*
* #param string $query - whatever expression contains placeholders
* #param mixed $arg,... unlimited number of arguments to match placeholders in the expression
* #return string - initial expression with placeholders substituted with data.
*/
public function parse()
{
return $this->prepareQuery(func_get_args());
}
/**
* function to implement whitelisting feature
* sometimes we can't allow a non-validated user-supplied data to the query even through placeholder
* especially if it comes down to SQL OPERATORS
*
* Example:
*
* $order = $db->whiteList($_GET['order'], array('name','price'));
* $dir = $db->whiteList($_GET['dir'], array('ASC','DESC'));
* if (!$order || !dir) {
* throw new http404(); //non-expected values should cause 404 or similar response
* }
* $sql = "SELECT * FROM table ORDER BY ?p ?p LIMIT ?i,?i"
* $data = $db->getArr($sql, $order, $dir, $start, $per_page);
*
* #param string $iinput - field name to test
* #param array $allowed - an array with allowed variants
* #param string $default - optional variable to set if no match found. Default to false.
* #return string|FALSE - either sanitized value or FALSE
*/
public function whiteList($input,$allowed,$default=FALSE)
{
$found = array_search($input,$allowed);
return ($found === FALSE) ? $default : $allowed[$found];
}
/**
* function to filter out arrays, for the whitelisting purposes
* useful to pass entire superglobal to the INSERT or UPDATE query
* OUGHT to be used for this purpose,
* as there could be fields to which user should have no access to.
*
* Example:
* $allowed = array('title','url','body','rating','term','type');
* $data = $db->filterArray($_POST,$allowed);
* $sql = "INSERT INTO ?n SET ?u";
* $db->query($sql,$table,$data);
*
* #param array $input - source array
* #param array $allowed - an array with allowed field names
* #return array filtered out source array
*/
public function filterArray($input,$allowed)
{
foreach(array_keys($input) as $key )
{
if ( !in_array($key,$allowed) )
{
unset($input[$key]);
}
}
return $input;
}
/**
* Function to get last executed query.
*
* #return string|NULL either last executed query or NULL if were none
*/
public function lastQuery()
{
$last = end($this->stats);
return $last['query'];
}
/**
* Function to get all query statistics.
*
* #return array contains all executed queries with timings and errors
*/
public function getStats()
{
return $this->stats;
}
/**
* private function which actually runs a query against Mysql server.
* also logs some stats like profiling info and error message
*
* #param string $query - a regular SQL query
* #return mysqli result resource or FALSE on error
*/
private function rawQuery($query)
{
$start = microtime(TRUE);
$res = mysqli_query($this->conn, $query);
$timer = microtime(TRUE) - $start;
$this->stats[] = array(
'query' => $query,
'start' => $start,
'timer' => $timer,
);
if (!$res)
{
$error = mysqli_error($this->conn);
end($this->stats);
$key = key($this->stats);
$this->stats[$key]['error'] = $error;
$this->cutStats();
$this->error("$error. Full query: [$query]");
}
$this->cutStats();
return $res;
}
private function prepareQuery($args)
{
$query = '';
$raw = array_shift($args);
$array = preg_split('~(\?[nsiuap])~u',$raw,null,PREG_SPLIT_DELIM_CAPTURE);
$anum = count($args);
$pnum = floor(count($array) / 2);
if ( $pnum != $anum )
{
$this->error("Number of args ($anum) doesn't match number of placeholders ($pnum) in [$raw]");
}
foreach ($array as $i => $part)
{
if ( ($i % 2) == 0 )
{
$query .= $part;
continue;
}
$value = array_shift($args);
switch ($part)
{
case '?n':
$part = $this->escapeIdent($value);
break;
case '?s':
$part = $this->escapeString($value);
break;
case '?i':
$part = $this->escapeInt($value);
break;
case '?a':
$part = $this->createIN($value);
break;
case '?u':
$part = $this->createSET($value);
break;
case '?p':
$part = $value;
break;
}
$query .= $part;
}
return $query;
}
private function escapeInt($value)
{
if ($value === NULL)
{
return 'NULL';
}
if(!is_numeric($value))
{
$this->error("Integer (?i) placeholder expects numeric value, ".gettype($value)." given");
return FALSE;
}
if (is_float($value))
{
$value = number_format($value, 0, '.', ''); // may lose precision on big numbers
}
return $value;
}
private function escapeString($value)
{
if ($value === NULL)
{
return 'NULL';
}
return "'".mysqli_real_escape_string($this->conn,$value)."'";
}
private function escapeIdent($value)
{
if ($value)
{
return "`".str_replace("`","``",$value)."`";
} else {
$this->error("Empty value for identifier (?n) placeholder");
}
}
private function createIN($data)
{
if (!is_array($data))
{
$this->error("Value for IN (?a) placeholder should be array");
return;
}
if (!$data)
{
return 'NULL';
}
$query = $comma = '';
foreach ($data as $value)
{
$query .= $comma.$this->escapeString($value);
$comma = ",";
}
return $query;
}
private function createSET($data)
{
if (!is_array($data))
{
$this->error("SET (?u) placeholder expects array, ".gettype($data)." given");
return;
}
if (!$data)
{
$this->error("Empty array for SET (?u) placeholder");
return;
}
$query = $comma = '';
foreach ($data as $key => $value)
{
$query .= $comma.$this->escapeIdent($key).'='.$this->escapeString($value);
$comma = ",";
}
return $query;
}
private function error($err)
{
$err = __CLASS__.": ".$err;
if ( $this->emode == 'error' )
{
$err .= ". Error initiated in ".$this->caller().", thrown";
trigger_error($err,E_USER_ERROR);
} else {
throw new $this->exname($err);
}
}
private function caller()
{
$trace = debug_backtrace();
$caller = '';
foreach ($trace as $t)
{
if ( isset($t['class']) && $t['class'] == __CLASS__ )
{
$caller = $t['file']." on line ".$t['line'];
} else {
break;
}
}
return $caller;
}
/**
* On a long run we can eat up too much memory with mere statsistics
* Let's keep it at reasonable size, leaving only last 100 entries.
*/
private function cutStats()
{
if ( count($this->stats) > 100 )
{
reset($this->stats);
$first = key($this->stats);
unset($this->stats[$first]);
}
}
}
//HOW I'M CURRENTLY CONNECTING TO THE DATABASE & CREATING GLOBAL VAR
global $db;
$db = new SafeMySQL('localhost', 'user', 'password', 'database');
This is the class I would like to extend the above database class to:
class News
{
public $news_id;
var $author;
var $title;
var $body;
var $date;
var $comments_count;
function __construct($id)
{
global $db;
$row = $db->getRow('SELECT *
FROM news_articles
WHERE id = ?i', $id);
$this->news_id = $row[id];
$this->author = $row[author];
$this->title = $row[title];
$this->body = $row[body];
$this->date = $row[date];
$this->comments_count = $this->countComments();
}
public static function getAllArticles(){
global $db;
$all_articles_array = $db->getAll('SELECT id
FROM news_articles ORDER BY date DESC');
return $all_articles_array;
}
Please do not use the word 'extends'. It has a very special meaning and may confuse a reader. You rather need to 'use' another class' instance in this .
Although in my opinion using global keyword for the site-wide global variables is all right, you'd be teared in pieces if spotted by local 'global police'. So, it's safer to pass a $db object into constructor and assign it as a class property:
class News
{
public $news_id;
private $db;
var $author;
var $title;
var $body;
var $date;
var $comments_count;
function __construct($db, $id)
{
$this->db = $db;
$sql = 'SELECT * FROM news_articles WHERE id = ?i';
$row = $this->db->getRow($sql, $id);
$this->news_id = $row['id'];
$this->author = $row['author'];
$this->title = $row['title'];
$this->body = $row['body'];
$this->date = $row['date'];
$this->comments_count = $this->countComments();
}
public static function getAllArticlesIds()
{
$sql = 'SELECT id FROM news_articles ORDER BY date DESC';
return $thus->db->getCol($sql);
}
}
Note that I renamed the other method and used getCol() method here as you are selecting only one column.
However i don't quite understand why do you set some properties in the constructor. It seems you are confusing two classes - News and Article. It's for the single Article object you have to initialize it's properties in the constructor. While for the News I doubt it is the right way.
I'm not sure if I understand your problem. However, I notice that SafeMySql does not provide the connection handle. It might help to add this:
/**
* Function to get the connection handle.
* Addition to original SafeDB.
*
* Examples:
* mysqli_autocommit($db->getHandle(),FALSE);
* mysqli_commit($db->getHandle());
*
* #param string $getHandle - an SQL connection handle
* #return object
*/
public function getHandle()
{
return $this->conn;
}

Integrity constraint violation: 1052 Column 'position' in order clause is ambiguous (PHP, MySQL)

Please help I have done all I can do to figure this out to no avail....
here is the error:
"a:5:{i:0;s:100:"SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'position' in order clause is ambiguous";i:1;s:3411:"#0 "/home/saes/public_html/lib/Zend/Db/Statement.php(300):"
here is the file:
abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
{
/**
* #var resource|object The driver level statement object/resource
*/
protected $_stmt = null;
/**
* #var Zend_Db_Adapter_Abstract
*/
protected $_adapter = null;
/**
* The current fetch mode.
*
* #var integer
*/
protected $_fetchMode = Zend_Db::FETCH_ASSOC;
/**
* Attributes.
*
* #var array
*/
protected $_attribute = array();
/**
* Column result bindings.
*
* #var array
*/
protected $_bindColumn = array();
/**
* Query parameter bindings; covers bindParam() and bindValue().
*
* #var array
*/
protected $_bindParam = array();
/**
* SQL string split into an array at placeholders.
*
* #var array
*/
protected $_sqlSplit = array();
/**
* Parameter placeholders in the SQL string by position in the split array.
*
* #var array
*/
protected $_sqlParam = array();
/**
* #var Zend_Db_Profiler_Query
*/
protected $_queryId = null;
/**
* Constructor for a statement.
*
* #param Zend_Db_Adapter_Abstract $adapter
* #param mixed $sql Either a string or Zend_Db_Select.
*/
public function __construct($adapter, $sql)
{
$this->_adapter = $adapter;
if ($sql instanceof Zend_Db_Select) {
$sql = $sql->assemble();
}
$this->_parseParameters($sql);
$this->_prepare($sql);
$this->_queryId = $this->_adapter->getProfiler()->queryStart($sql);
}
/**
* Internal method called by abstract statment constructor to setup
* the driver level statement
*
* #return void
*/
protected function _prepare($sql)
{
return;
}
/**
* #param string $sql
* #return void
*/
protected function _parseParameters($sql)
{
$sql = $this->_stripQuoted($sql);
// split into text and params
$this->_sqlSplit = preg_split('/(\?|\:[a-zA-Z0-9_]+)/',
$sql, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
// map params
$this->_sqlParam = array();
foreach ($this->_sqlSplit as $key => $val) {
if ($val == '?') {
if ($this->_adapter->supportsParameters('positional') === false) {
/**
* #see Zend_Db_Statement_Exception
*/
#require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$val'");
}
} else if ($val[0] == ':') {
if ($this->_adapter->supportsParameters('named') === false) {
/**
* #see Zend_Db_Statement_Exception
*/
#require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception("Invalid bind-variable name '$val'");
}
}
$this->_sqlParam[] = $val;
}
// set up for binding
$this->_bindParam = array();
}
/**
* Remove parts of a SQL string that contain quoted strings
* of values or identifiers.
*
* #param string $sql
* #return string
*/
protected function _stripQuoted($sql)
{
// get the character for delimited id quotes,
// this is usually " but in MySQL is `
$d = $this->_adapter->quoteIdentifier('a');
$d = $d[0];
// get the value used as an escaped delimited id quote,
// e.g. \" or "" or \`
$de = $this->_adapter->quoteIdentifier($d);
$de = substr($de, 1, 2);
$de = str_replace('\\', '\\\\', $de);
// get the character for value quoting
// this should be '
$q = $this->_adapter->quote('a');
$q = $q[0];
// get the value used as an escaped quote,
// e.g. \' or ''
$qe = $this->_adapter->quote($q);
$qe = substr($qe, 1, 2);
$qe = str_replace('\\', '\\\\', $qe);
// get a version of the SQL statement with all quoted
// values and delimited identifiers stripped out
// remove "foo\"bar"
$sql = preg_replace("/$q($qe|\\\\{2}|[^$q])*$q/", '', $sql);
// remove 'foo\'bar'
if (!empty($q)) {
$sql = preg_replace("/$q($qe|[^$q])*$q/", '', $sql);
}
return $sql;
}
/**
* Bind a column of the statement result set to a PHP variable.
*
* #param string $column Name the column in the result set, either by
* position or by name.
* #param mixed $param Reference to the PHP variable containing the value.
* #param mixed $type OPTIONAL
* #return bool
*/
public function bindColumn($column, &$param, $type = null)
{
$this->_bindColumn[$column] =& $param;
return true;
}
/**
* Binds a parameter to the specified variable name.
*
* #param mixed $parameter Name the parameter, either integer or string.
* #param mixed $variable Reference to PHP variable containing the value.
* #param mixed $type OPTIONAL Datatype of SQL parameter.
* #param mixed $length OPTIONAL Length of SQL parameter.
* #param mixed $options OPTIONAL Other options.
* #return bool
*/
public function bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
{
if (!is_int($parameter) && !is_string($parameter)) {
/**
* #see Zend_Db_Statement_Exception
*/
#require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception('Invalid bind-variable position');
}
$position = null;
if (($intval = (int) $parameter) > 0 && $this->_adapter->supportsParameters('positional')) {
if ($intval >= 1 || $intval <= count($this->_sqlParam)) {
$position = $intval;
}
} else if ($this->_adapter->supportsParameters('named')) {
if ($parameter[0] != ':') {
$parameter = ':' . $parameter;
}
if (in_array($parameter, $this->_sqlParam) !== false) {
$position = $parameter;
}
}
if ($position === null) {
/**
* #see Zend_Db_Statement_Exception
*/
#require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$parameter'");
}
// Finally we are assured that $position is valid
$this->_bindParam[$position] =& $variable;
return $this->_bindParam($position, $variable, $type, $length, $options);
}
/**
* Binds a value to a parameter.
*
* #param mixed $parameter Name the parameter, either integer or string.
* #param mixed $value Scalar value to bind to the parameter.
* #param mixed $type OPTIONAL Datatype of the parameter.
* #return bool
*/
public function bindValue($parameter, $value, $type = null)
{
return $this->bindParam($parameter, $value, $type);
}
/**
* Executes a prepared statement.
*
* #param array $params OPTIONAL Values to bind to parameter placeholders.
* #return bool
*/
public function execute(array $params = null)
{
/*
* Simple case - no query profiler to manage.
*/
if ($this->_queryId === null) {
return $this->_execute($params);
}
/*
* Do the same thing, but with query profiler
* management before and after the execute.
*/
$prof = $this->_adapter->getProfiler();
$qp = $prof->getQueryProfile($this->_queryId);
if ($qp->hasEnded()) {
$this->_queryId = $prof->queryClone($qp);
$qp = $prof->getQueryProfile($this->_queryId);
}
if ($params !== null) {
$qp->bindParams($params);
} else {
$qp->bindParams($this->_bindParam);
}
$qp->start($this->_queryId);
$retval = $this->_execute($params);
$prof->queryEnd($this->_queryId);
return $retval;
}
/**
* Returns an array containing all of the result set rows.
*
* #param int $style OPTIONAL Fetch mode.
* #param int $col OPTIONAL Column number, if fetch mode is by column.
* #return array Collection of rows, each in a format by the fetch mode.
*/
public function fetchAll($style = null, $col = null)
{
$data = array();
if ($style === Zend_Db::FETCH_COLUMN && $col === null) {
$col = 0;
}
if ($col === null) {
while ($row = $this->fetch($style)) {
$data[] = $row;
}
} else {
while (false !== ($val = $this->fetchColumn($col))) {
$data[] = $val;
}
}
return $data;
}
/**
* Returns a single column from the next row of a result set.
*
* #param int $col OPTIONAL Position of the column to fetch.
* #return string One value from the next row of result set, or false.
*/
public function fetchColumn($col = 0)
{
$data = array();
$col = (int) $col;
$row = $this->fetch(Zend_Db::FETCH_NUM);
if (!is_array($row)) {
return false;
}
return $row[$col];
}
/**
* Fetches the next row and returns it as an object.
*
* #param string $class OPTIONAL Name of the class to create.
* #param array $config OPTIONAL Constructor arguments for the class.
* #return mixed One object instance of the specified class, or false.
*/
public function fetchObject($class = 'stdClass', array $config = array())
{
$obj = new $class($config);
$row = $this->fetch(Zend_Db::FETCH_ASSOC);
if (!is_array($row)) {
return false;
}
foreach ($row as $key => $val) {
$obj->$key = $val;
}
return $obj;
}
/**
* Retrieve a statement attribute.
*
* #param string $key Attribute name.
* #return mixed Attribute value.
*/
public function getAttribute($key)
{
if (array_key_exists($key, $this->_attribute)) {
return $this->_attribute[$key];
}
}
/**
* Set a statement attribute.
*
* #param string $key Attribute name.
* #param mixed $val Attribute value.
* #return bool
*/
public function setAttribute($key, $val)
{
$this->_attribute[$key] = $val;
}
/**
* Set the default fetch mode for this statement.
*
* #param int $mode The fetch mode.
* #return bool
* #throws Zend_Db_Statement_Exception
*/
public function setFetchMode($mode)
{
switch ($mode) {
case Zend_Db::FETCH_NUM:
case Zend_Db::FETCH_ASSOC:
case Zend_Db::FETCH_BOTH:
case Zend_Db::FETCH_OBJ:
$this->_fetchMode = $mode;
break;
case Zend_Db::FETCH_BOUND:
default:
$this->closeCursor();
/**
* #see Zend_Db_Statement_Exception
*/
#require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception('invalid fetch mode');
break;
}
}
/**
* Helper function to map retrieved row
* to bound column variables
*
* #param array $row
* #return bool True
*/
public function _fetchBound($row)
{
foreach ($row as $key => $value) {
// bindColumn() takes 1-based integer positions
// but fetch() returns 0-based integer indexes
if (is_int($key)) {
$key++;
}
// set results only to variables that were bound previously
if (isset($this->_bindColumn[$key])) {
$this->_bindColumn[$key] = $value;
}
}
return true;
}
/**
* Gets the Zend_Db_Adapter_Abstract for this
* particular Zend_Db_Statement object.
*
* #return Zend_Db_Adapter_Abstract
*/
public function getAdapter()
{
return $this->_adapter;
}
/**
* Gets the resource or object setup by the
* _parse
* #return unknown_type
*/
public function getDriverStatement()
{
return $this->_stmt;
}
}
The class isn't the problem, the sql-statement you are trying to execute is. You probably have a join between two tables and are trying to sort by position, without specifing which table the column should be of.

Categories