Hi
I've created a DBAL module for a framework, And added Prepared Statements support to it. Here's the whole class code:
<?php
/*
* Database Access Layer
* by AbiusX[at]gmail[dot]com
* Version 2.2.1
* Customized for MySQL
*/
//TODO: the current fetch method for Prepared Statements copies the arrays so badly!
//TODO: add support for transactions
//TODO: add support for stored procedures
//TODO: add support for triggers and Vies
class DBAL {
public $DB;
public $Result;
public $m_username,$m_password,$m_databasename;
public $QueryCount;
function __construct($Username,$Password,$DatabaseName)
{
$this->DB=new mysqli("localhost",$Username,$Password,$DatabaseName);
if (mysqli_connect_errno())
die( "Unable to connect to database.");
//$this->DB->select_db($DatabaseName);
$this->m_username=$Username;
$this->m_password=$Password;
$this->m_databasename=$DatabaseName;
}
function __destruct()
{
$this->DB->close();
}
function LastInsertID()
{
return $this->LastID();
}
function LastID()
{
return $this->DB->insert_id;
}
function Escape()
{
$args=func_get_args();
foreach ($args as $arg)
$this->DB->real_escape_string($arg);
}
function Query($QueryString)
{
$this->QueryCount+=1;
$this->Result=$this->DB->query($QueryString);
}
function NextResult()
{
if ($this->ResultCount())
return $this->Result->fetch_array(MYSQLI_ASSOC);
else
return false;
}
function AllResult()
{
if ($this->ResultCount())
{
$out=array();
while ($r=$this->Result->fetch_array(MYSQLI_ASSOC)) $out[]=$r;
return $out;
}
else return false;
}
function ResultCount()
{
return $this->Result->num_rows;
}
function AffectedRows()
{
return $this->DB->affected_rows();
}
function FullQuery($QueryString)
{
$this->Query($QueryString);
return $this->AllResult();
}
function AutoQuery($QueryString)
{
return $this->FullQuery($QueryString);
}
function AutoPrepared()
{
$st=new PreparedStatement($this);
$args=func_get_args();
return call_user_func_array(array($st,"Auto"),$args);
}
function AutoPrepare()
{
$args=func_get_args();
return call_user_func_array(array($this,"AutoPrepared"),$args);
}
function Execute()
{
$args=func_get_args();
return call_user_func_array(array($this,"AutoPrepared"),$args);
}
function RunPrepared()
{
$args=func_get_args();
return call_user_func_array(array($this,"AutoPrepared"),$args);
}
}
class PreparedStatement {
public $DB;
public $Statement;
public $DBAL;
function __construct(DBAL $DB,$Query=0)
{
$this->DB=$DB->DB;
$this->DBAL=$DB;
if ($Query)
$this->Prepare($Query);
}
function Auto($Query)
{
$IID=false;
$this->Prepare($Query);
if (substr(strtoupper($Query),0,6)=="INSERT" or substr(strtoupper($Query),0,7)=="REPLACE" )
$IID=true;
if (func_num_args()>1)
{
$args=func_get_args();
array_shift($args);
//array_shift($args);
call_user_func_array(array($this,"Bind"),$args);
$this->Execute();
if (!$IID) return $this->AllResult();
else return $this->LastID();
}
}
function Prepare($QueryString) //replace values with ?
{
if (!$stmt=$this->DB->prepare($QueryString))
die ("Unable to prepare statement: ".$QueryString." reason: ".$this->DB->error);
$this->Statement=$stmt;
}
function __destruct()
{
if ($this->Statement) $this->Statement->close();
}
private function VarType($var)
{
if (is_string($var))
return "s";
elseif (is_float($var) or is_double($var))
return "d";
elseif (is_bool($var) or is_int($var) or is_long($var))
return "i";
else
return "b";
}
function Bind()
{
$args=func_get_args();
$types="";
/*
foreach ($args as $arg)
{
$types.=$this->VarType($arg);
}
*/
$types=str_repeat("s",count($args));
$newarr=array_merge(array($types),$args);
call_user_func_array(array($this->Statement
,'bind_param')
,$newarr);
}
function Execute()
{
$this->DBAL->QueryCount+=1;
$this->Statement->execute();
}
function ResultCount()
{
return $this->Statement->num_rows();
}
function LastID()
{
return $this->Statement->insert_id;
}
function NextResult()
{
$data = $this->Statement->result_metadata();
$fields = array();
$out = array();
$count = 0;
while($field = mysqli_fetch_field($data))
$fields[$count++] = &$out[$field->name];
call_user_func_array(array($this->Statement,"bind_result"), $fields);
$this->Statement->fetch();
return (count($out) == 0) ? false : $out;
}
function AllResult()
{
$data = $this->Statement->result_metadata();
if (!$data) return ;
$fields = array();
$out = array();
$count = 0;
while($field = mysqli_fetch_field($data))
$fields[$count++] = &$out[$field->name];
call_user_func_array(array($this->Statement,"bind_result"), $fields);
$output=array();
while ($this->Statement->fetch())
$output[]=unserialize(serialize($out)); //TODO: fix here
return (count($output) == 0) ? null : $output;
}
}
?>
The problem is with the last lines of code where I say
$output[]=unserialize(serialize($out)); //TODO: fix here
I know that when you code $a=$b;
and both are arrays, the arrays are copied. So I assume when I add $out to $output, A copy of it would be added, but it wont. And nothing seems to work, So I had to call a few functions on it to copy it actually!
If I do not copy it, All the result rows would be the last row!
Please help?