ZF2 ldap pagination - php

I'm having some issues with the LDAP libraries and Active Directory. I cannot search with the LDAP libraries if the parameters will return more than 1000 results, because of the limitations of AD. Also there doesn't seem to be a way to paginate the results using the ZF2 LDAP libraries. I know how to paginate but i would rather use a ZF2 in-built method if one exists.
Is there something I'm missing or do I have to create my own method to achieve this?
P.S. I have looked over the manual and the code but i cannot see any methods to achieve this.

This is what i did to get around the issue
/**
* An LDAP search routine for finding information and returning paginated results
*
* Options can be either passed as single parameters according to the
* method signature or as an array with one or more of the following keys
* - filter
* - baseDn
* - scope
* - attributes
* - sort
* - collectionClass
* - sizelimit
* - timelimit
*
* #param string|Filter\AbstractFilter|array $filter
* #param string|Dn|null $basedn
* #param array $attributes
* #param string|null $sort
* #param string|null $collectionClass
* #param integer $timelimit
* #param integer $pageSize
* #return Array
* #throws Exception\LdapException
*/
public function multiPageSearch(
$filter, $basedn = null, array $attributes = array(), $sort = null,
$collectionClass = null, $timelimit = 0, $pageSize = 1000
)
{
if (is_array($filter)) {
$options = array_change_key_case($filter, CASE_LOWER);
foreach ($options as $key => $value) {
switch ($key) {
case 'filter':
case 'basedn':
case 'scope':
case 'sort':
$$key = $value;
break;
case 'attributes':
if (is_array($value)) {
$attributes = $value;
}
break;
case 'collectionclass':
$collectionClass = $value;
break;
case 'sizelimit':
case 'timelimit':
$$key = (int) $value;
break;
}
}
}
if ($basedn === null) {
$basedn = $this->getBaseDn();
} elseif ($basedn instanceof Dn) {
$basedn = $basedn->toString();
}
if ($filter instanceof Filter\AbstractFilter) {
$filter = $filter->toString();
}
$resource = $this->getResource();
$results = new \ArrayIterator;
Stdlib\ErrorHandler::start(E_WARNING);
$cookie = '';
do {
ldap_control_paged_result($resource, $pageSize, true, $cookie);
$result = ldap_search($resource, $basedn, $filter, $attributes, 0, $pageSize, $timelimit);
if ($sort !== null && is_string($sort)) {
$isSorted = ldap_sort($resource, $result, $sort);
if ($isSorted === false) {
throw new Exception\LdapException($this, 'sorting: ' . $sort);
}
}
$entries = new \ArrayIterator(ldap_get_entries($resource, $result));
foreach ($entries as $e) {
$results[] = $e;
}
ldap_control_paged_result_response($resource, $result, $cookie);
} while($cookie !== null && $cookie != '');
Stdlib\ErrorHandler::stop();
if ($results->count() == 0) {
throw new Exception\LdapException($this, 'searching: ' . $filter);
}
return $results;
}
This class/method was made to extends the Zend\Ldap\Ldap class, it will allow more than 1000 results to be returned, but it will not return them in the same format as the Ldap::search method.

Check out the Zend LDAP Library: Zend\Ldap\Ldap.php
/**
* A global LDAP search routine for finding information.
*
* Options can be either passed as single parameters according to the
* method signature or as an array with one or more of the following keys
* - filter
* - baseDn
* - scope
* - attributes
* - sort
* - collectionClass
* - sizelimit
* - timelimit
*
* #param string|Filter\AbstractFilter|array $filter
* #param string|Dn|null $basedn
* #param integer $scope
* #param array $attributes
* #param string|null $sort
* #param string|null $collectionClass
* #param integer $sizelimit
* #param integer $timelimit
* #return Collection
* #throws Exception\LdapException
*/
public function search($filter, $basedn = null, $scope = self::SEARCH_SCOPE_SUB, array $attributes = array(),
$sort = null, $collectionClass = null, $sizelimit = 0, $timelimit = 0
)
{
// ..
}
You can see from the signature you can pass in a parameter to limit the resultset.
A very simple wrapper for this method:
/**
* Search for entries.
*
* #parram string
* #param string
* #param int
* #param int
* #return array
*/
public function search($filter, $basedn = null, $scope = \Zend\Ldap\Ldap::SEARCH_SCOPE_SUB, $sizelimit = 0)
{
$attributes = array();
$sort = null;
$collectionClass = null;
$result = $this->_getLdap()
->search($filter, $basedn, $scope, $attributes, $sort, $collectionClass, $sizelimit)
;
return $result;
}
A simple example to find users could be somethig like this:
/**
* Get all Users..
*
* #param string
* #return \Zend\Ldap\Collection
*/
public function getUsers($baseDn, $sizelimit = 0)
{
return $this->search('(objectCategory=user)', $baseDn, $sizelimit);
}
You could then Use an Iterator Adapter with the Paginator to get this to work correctly:
use Zend\Paginator\Adapter\Iterator as IteratorAdapter;
// ..
$users = $this->_getMyLdapService()->getUsers();
$paginator = new Paginator(new IteratorAdapter($users));

Related

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

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;
}

MySQLi Wrapper: fetch_field() on a non-object

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);

Why I am getting Class "SoapClient' not found in..etc" [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WAMP Stack PHP “Fatal error: Class ‘SoapClient’ not found”
I downloaded a library from this site library and when I tried to use it's examples it says : "Fatal error: Class 'SoapClient' not found in C:\wamp\www\Amazon-ECS\Exeu-Amazon-ECS-PHP-Library-9030053\lib\AmazonECS.class.php on line 231" How should I able to fix this?
<?php
/**
* Amazon ECS Class
* http://www.amazon.com
* =====================
*
* This class fetchs productinformation via the Product Advertising API by Amazon (formerly ECS).
* It supports three basic operations: ItemSearch, ItemLookup and BrowseNodeLookup.
* These operations could be expanded with extra prarmeters to specialize the query.
*
* Requirement is the PHP extension SOAP.
*
* #package AmazonECS
* #license http://www.gnu.org/licenses/gpl.txt GPL
* #version 1.3.4-DEV
* #author Exeu <exeu65#googlemail.com>
* #contributor Julien Chaumond <chaumond#gmail.com>
* #link http://github.com/Exeu/Amazon-ECS-PHP-Library/wiki Wiki
* #link http://github.com/Exeu/Amazon-ECS-PHP-Library Source
*/
class AmazonECS
{
const RETURN_TYPE_ARRAY = 1;
const RETURN_TYPE_OBJECT = 2;
/**
* Baseconfigurationstorage
*
* #var array
*/
private $requestConfig = array(
'requestDelay' => false
);
/**
* Responseconfigurationstorage
*
* #var array
*/
private $responseConfig = array(
'returnType' => self::RETURN_TYPE_OBJECT,
'responseGroup' => 'Small',
'optionalParameters' => array()
);
/**
* All possible locations
*
* #var array
*/
private $possibleLocations = array('de', 'com', 'co.uk', 'ca', 'fr', 'co.jp', 'it', 'cn', 'es');
/**
* The WSDL File
*
* #var string
*/
protected $webserviceWsdl = 'http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl';
/**
* The SOAP Endpoint
*
* #var string
*/
protected $webserviceEndpoint = 'https://webservices.amazon.%%COUNTRY%%/onca/soap?Service=AWSECommerceService';
/**
* #param string $accessKey
* #param string $secretKey
* #param string $country
* #param string $associateTag
*/
public function __construct($accessKey, $secretKey, $country, $associateTag)
{
if (empty($accessKey) || empty($secretKey))
{
throw new Exception('No Access Key or Secret Key has been set');
}
$this->requestConfig['accessKey'] = $accessKey;
$this->requestConfig['secretKey'] = $secretKey;
$this->associateTag($associateTag);
$this->country($country);
}
/**
* execute search
*
* #param string $pattern
*
* #return array|object return type depends on setting
*
* #see returnType()
*/
public function search($pattern, $nodeId = null)
{
if (false === isset($this->requestConfig['category']))
{
throw new Exception('No Category given: Please set it up before');
}
$browseNode = array();
if (null !== $nodeId && true === $this->validateNodeId($nodeId))
{
$browseNode = array('BrowseNode' => $nodeId);
}
$params = $this->buildRequestParams('ItemSearch', array_merge(
array(
'Keywords' => $pattern,
'SearchIndex' => $this->requestConfig['category']
),
$browseNode
));
return $this->returnData(
$this->performSoapRequest("ItemSearch", $params)
);
}
/**
* execute ItemLookup request
*
* #param string $asin
*
* #return array|object return type depends on setting
*
* #see returnType()
*/
public function lookup($asin)
{
$params = $this->buildRequestParams('ItemLookup', array(
'ItemId' => $asin,
));
return $this->returnData(
$this->performSoapRequest("ItemLookup", $params)
);
}
/**
* Implementation of BrowseNodeLookup
* This allows to fetch information about nodes (children anchestors, etc.)
*
* #param integer $nodeId
*/
public function browseNodeLookup($nodeId)
{
$this->validateNodeId($nodeId);
$params = $this->buildRequestParams('BrowseNodeLookup', array(
'BrowseNodeId' => $nodeId
));
return $this->returnData(
$this->performSoapRequest("BrowseNodeLookup", $params)
);
}
/**
* Implementation of SimilarityLookup
* This allows to fetch information about product related to the parameter product
*
* #param string $asin
*/
public function similarityLookup($asin)
{
$params = $this->buildRequestParams('SimilarityLookup', array(
'ItemId' => $asin
));
return $this->returnData(
$this->performSoapRequest("SimilarityLookup", $params)
);
}
/**
* Builds the request parameters
*
* #param string $function
* #param array $params
*
* #return array
*/
protected function buildRequestParams($function, array $params)
{
$associateTag = array();
if(false === empty($this->requestConfig['associateTag']))
{
$associateTag = array('AssociateTag' => $this->requestConfig['associateTag']);
}
return array_merge(
$associateTag,
array(
'AWSAccessKeyId' => $this->requestConfig['accessKey'],
'Request' => array_merge(
array('Operation' => $function),
$params,
$this->responseConfig['optionalParameters'],
array('ResponseGroup' => $this->prepareResponseGroup())
)));
}
/**
* Prepares the responsegroups and returns them as array
*
* #return array|prepared responsegroups
*/
protected function prepareResponseGroup()
{
if (false === strstr($this->responseConfig['responseGroup'], ','))
return $this->responseConfig['responseGroup'];
return explode(',', $this->responseConfig['responseGroup']);
}
/**
* #param string $function Name of the function which should be called
* #param array $params Requestparameters 'ParameterName' => 'ParameterValue'
*
* #return array The response as an array with stdClass objects
*/
protected function performSoapRequest($function, $params)
{
if (true === $this->requestConfig['requestDelay']) {
sleep(1);
}
$soapClient = new SoapClient(
$this->webserviceWsdl,
array('exceptions' => 1)
);
$soapClient->__setLocation(str_replace(
'%%COUNTRY%%',
$this->responseConfig['country'],
$this->webserviceEndpoint
));
$soapClient->__setSoapHeaders($this->buildSoapHeader($function));
return $soapClient->__soapCall($function, array($params));
}
/**
* Provides some necessary soap headers
*
* #param string $function
*
* #return array Each element is a concrete SoapHeader object
*/
protected function buildSoapHeader($function)
{
$timeStamp = $this->getTimestamp();
$signature = $this->buildSignature($function . $timeStamp);
return array(
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'AWSAccessKeyId',
$this->requestConfig['accessKey']
),
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'Timestamp',
$timeStamp
),
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'Signature',
$signature
)
);
}
/**
* provides current gm date
*
* primary needed for the signature
*
* #return string
*/
final protected function getTimestamp()
{
return gmdate("Y-m-d\TH:i:s\Z");
}
/**
* provides the signature
*
* #return string
*/
final protected function buildSignature($request)
{
return base64_encode(hash_hmac("sha256", $request, $this->requestConfig['secretKey'], true));
}
/**
* Basic validation of the nodeId
*
* #param integer $nodeId
*
* #return boolean
*/
final protected function validateNodeId($nodeId)
{
if (false === is_numeric($nodeId) || $nodeId <= 0)
{
throw new InvalidArgumentException(sprintf('Node has to be a positive Integer.'));
}
return true;
}
/**
* Returns the response either as Array or Array/Object
*
* #param object $object
*
* #return mixed
*/
protected function returnData($object)
{
switch ($this->responseConfig['returnType'])
{
case self::RETURN_TYPE_OBJECT:
return $object;
break;
case self::RETURN_TYPE_ARRAY:
return $this->objectToArray($object);
break;
default:
throw new InvalidArgumentException(sprintf(
"Unknwon return type %s", $this->responseConfig['returnType']
));
break;
}
}
/**
* Transforms the responseobject to an array
*
* #param object $object
*
* #return array An arrayrepresentation of the given object
*/
protected function objectToArray($object)
{
$out = array();
foreach ($object as $key => $value)
{
switch (true)
{
case is_object($value):
$out[$key] = $this->objectToArray($value);
break;
case is_array($value):
$out[$key] = $this->objectToArray($value);
break;
default:
$out[$key] = $value;
break;
}
}
return $out;
}
/**
* set or get optional parameters
*
* if the argument params is null it will reutrn the current parameters,
* otherwise it will set the params and return itself.
*
* #param array $params the optional parameters
*
* #return array|AmazonECS depends on params argument
*/
public function optionalParameters($params = null)
{
if (null === $params)
{
return $this->responseConfig['optionalParameters'];
}
if (false === is_array($params))
{
throw new InvalidArgumentException(sprintf(
"%s is no valid parameter: Use an array with Key => Value Pairs", $params
));
}
$this->responseConfig['optionalParameters'] = $params;
return $this;
}
/**
* Set or get the country
*
* if the country argument is null it will return the current
* country, otherwise it will set the country and return itself.
*
* #param string|null $country
*
* #return string|AmazonECS depends on country argument
*/
public function country($country = null)
{
if (null === $country)
{
return $this->responseConfig['country'];
}
if (false === in_array(strtolower($country), $this->possibleLocations))
{
throw new InvalidArgumentException(sprintf(
"Invalid Country-Code: %s! Possible Country-Codes: %s",
$country,
implode(', ', $this->possibleLocations)
));
}
$this->responseConfig['country'] = strtolower($country);
return $this;
}
/**
* Setting/Getting the amazon category
*
* #param string $category
*
* #return string|AmazonECS depends on category argument
*/
public function category($category = null)
{
if (null === $category)
{
return isset($this->requestConfig['category']) ? $this->requestConfig['category'] : null;
}
$this->requestConfig['category'] = $category;
return $this;
}
/**
* Setting/Getting the responsegroup
*
* #param string $responseGroup Comma separated groups
*
* #return string|AmazonECS depends on responseGroup argument
*/
public function responseGroup($responseGroup = null)
{
if (null === $responseGroup)
{
return $this->responseConfig['responseGroup'];
}
$this->responseConfig['responseGroup'] = $responseGroup;
return $this;
}
/**
* Setting/Getting the returntype
* It can be an object or an array
*
* #param integer $type Use the constants RETURN_TYPE_ARRAY or RETURN_TYPE_OBJECT
*
* #return integer|AmazonECS depends on type argument
*/
public function returnType($type = null)
{
if (null === $type)
{
return $this->responseConfig['returnType'];
}
$this->responseConfig['returnType'] = $type;
return $this;
}
/**
* Setter/Getter of the AssociateTag.
* This could be used for late bindings of this attribute
*
* #param string $associateTag
*
* #return string|AmazonECS depends on associateTag argument
*/
public function associateTag($associateTag = null)
{
if (null === $associateTag)
{
return $this->requestConfig['associateTag'];
}
$this->requestConfig['associateTag'] = $associateTag;
return $this;
}
/**
* #deprecated use returnType() instead
*/
public function setReturnType($type)
{
return $this->returnType($type);
}
/**
* Setting the resultpage to a specified value.
* Allows to browse resultsets which have more than one page.
*
* #param integer $page
*
* #return AmazonECS
*/
public function page($page)
{
if (false === is_numeric($page) || $page <= 0)
{
throw new InvalidArgumentException(sprintf(
'%s is an invalid page value. It has to be numeric and positive',
$page
));
}
$this->responseConfig['optionalParameters'] = array_merge(
$this->responseConfig['optionalParameters'],
array("ItemPage" => $page)
);
return $this;
}
/**
* Enables or disables the request delay.
* If it is enabled (true) every request is delayed one second to get rid of the api request limit.
*
* Reasons for this you can read on this site:
* https://affiliate-program.amazon.com/gp/advertising/api/detail/faq.html
*
* By default the requestdelay is disabled
*
* #param boolean $enable true = enabled, false = disabled
*
* #return boolean|AmazonECS depends on enable argument
*/
public function requestDelay($enable = null)
{
if (false === is_null($enable) && true === is_bool($enable))
{
$this->requestConfig['requestDelay'] = $enable;
return $this;
}
return $this->requestConfig['requestDelay'];
}
}
The error appears to be caused by the version of PHP that you have does not have the SOAP extension enabled.
To resolve this simply start wamp, click on the wamp system tray icon. Within this screen select PHP then PHP extensions. This will display a list of extensions. Ensure that php_soap is ticked.
If you intend to access soap servers that use HTTPs then you will also ensure php_openssl is ticked.

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