Prepared Statements not working in mySQL / PHP [duplicate] - php
This question already has answers here:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
(2 answers)
Closed 1 year ago.
For some reason I keep getting this error when attempting to run prepared query with mysqli
mysqli_stmt::bind_result(): Number of bind variables doesn't match
number of fields in prepared statement
This db class works fine until I try to use a query with LEFT OUTER JOIN
I'm wondering if anyone knows why? I'll post the query, schema, etc.. below.
NOTE: I saw one question on here that suggested I specifically spell out all the field names I want to select, rather than use '*'(star). There are A LOT of fields involved and I spent almost an hour typing them all out. When I tested, it didn't change anything. I have omitted that and returned to using star just in case anyone was going to suggest I type them all out. Already tried. Doesn't help.
ALSO: This query works fine if I put it straight into phpMyAdmin, so it's a working query. Just throwing an error when trying to bind the result for some reason. Even if I remove the multiple joins and just have one left join it still throws the error about not having the correct parameter count. I don't get it.
Query Output by PHP
SELECT * FROM `SlipMaster`
left outer join `SlipMain`
on `SlipMaster`.`slipCode` = `SlipMain`.`slipCode`
left outer join `ContractMain`
on `SlipMain`.`slipContractId` = `ContractMain`.`id`
left outer join `ClientMain`
on `SlipMain`.`slipClientId` = `ClientMain`.`id`
left outer join `PaymentMain`
on `ContractMain`.`contractPaymentId` = `PaymentMain`.`id`
left outer join `VesselMain`
on `SlipMain`.`slipVesselId` = `VesselMain`.`id`
WHERE 1 = ?
PHP CODE USING MYSQLI DB CLASS
$from = '
`SlipMaster`
left outer join `SlipMain`
on `SlipMaster`.`slipCode` = `SlipMain`.`slipCode`
left outer join `ContractMain`
on `SlipMain`.`slipContractId` = `ContractMain`.`id`
left outer join `ClientMain`
on `SlipMain`.`slipClientId` = `ClientMain`.`id`
left outer join `PaymentMain`
on `ContractMain`.`contractPaymentId` = `PaymentMain`.`id`
left outer join `VesselMain`
on `SlipMain`.`slipVesselId` = `VesselMain`.`id`';
$dbi->new_query();
$dbi->add_param('i', '1');
$dbi->select($from, '*', '1=?');
PHP MYSQLI DB CLASS
<?php
class mysqliObject {
public $user = "";
public $pass = "";
public $name = "";
public $host = "";
public $_db;
public $_config;
public $MYSQLI_LINK = FALSE;
public $rows = FALSE;
public $last_error = FALSE;
public $last_query = FALSE;
public $result = FALSE;
public $last_id = FALSE;
public $paramTypeArray = [];
public $paramBindArray = [];
public function __construct() {
}
public function __destruct() {
$this->close();
}
public function connect() {
$this->host = $this->_config->get('DBHOST');
$this->name = $this->_config->get('DBNAME');
$this->user = $this->_config->get('DBUSER');
$this->pass = $this->_config->get('DBPASS');
$this->MYSQLI_LINK = new mysqli($this->host, $this->user, $this->pass, $this->name);
}
public function setDatabase($databaseConnection) {
$this->_db = $databaseConnection;
}
public function setConfig($config) {
$this->_config = $config;
}
public function close() {
#mysqli_close($this->MYSQLI_LINK);
}
public function get_hash($p) {
return password_hash($p, PASSWORD_BCRYPT, array("cost" => 10));
}
public function check_password($p, $h) {
return (password_verify($p, $h)) ? true : false;
}
public function get_rndkey($length=32) {
$random_string="";
while(strlen($random_string)<$length && $length > 0) {
$randnum = mt_rand(0,61);
$random_string .= ($randnum < 10) ?
chr($randnum+48) : ($randnum < 36 ?
chr($randnum+55) : $randnum+61);
}
return $random_string;
}
public function escape($value) {
return mysqli_real_escape_string($this->MYSQLI_LINK, $value);
}
public function get_lastid() {
return $this->MYSQLI_LINK->insert_id;
}
public function new_query() {
$this->paramTypeArray = Array();
$this->paramBindArray = Array();
}
public function add_param($t, $d) {
$this->paramTypeArray[] = $t;
$this->paramBindArray[] = $d;
}
// Shortcut for Select Method
public function s($t,$x, $d, $w) {
$this->new_query();
foreach($d as $v) {
$this->add_param($v['t'], $v['v']);
}
return $this->select($t, $x, $w) ? $this->result : false;
}
public function select($t, $d, $c) {
/* Types: s = string, i = integer, d = double, b = blob */
$a_params = array();
$param_type = '';
$n = count($this->paramTypeArray);
for($i = 0; $i < $n; $i++) {
$param_type .= $this->paramTypeArray[$i];
}
$a_params[] = & $param_type;
for($i = 0; $i < $n; $i++) {
$a_bind_params[] = $this->paramBindArray[$i];
}
for($i = 0; $i < $n; $i++) {
$a_params[] = & $a_bind_params[$i];
}
$q = 'SELECT '.$d.' FROM '.$t.' WHERE '.$c;
$s = $this->MYSQLI_LINK->prepare($q);
if($s === false) {
trigger_error('Wrong SQL: ' . $q . ' Error: ' . $this->MYSQLI_LINK->errno . ' ' . $this->MYSQLI_LINK->error, E_USER_ERROR);
}
call_user_func_array(array($s, 'bind_param'), $a_params);
$s->execute();
$meta = $s->result_metadata();
while ($field = $meta->fetch_field()) {
$var = $field->name;
$$var = null;
$fields[$var] = &$$var;
}
call_user_func_array(array($s,'bind_result'),$fields);
$i = 0;
while ($s->fetch()) {
$results[$i] = [];
foreach($fields as $k => $v) {
$results[$i][$k] = $v;
}
$i++;
}
$s->close();
$this->last_query = $q;
if (count($results) > 0) {
$this->result = $results;
return TRUE;
} else {
$this->last_error = mysqli_error($this->MYSQLI_LINK);
return FALSE;
}
return FALSE;
}
public function delete($t, $c) {
$a_params = array();
$param_type = '';
$n = count($this->paramTypeArray);
for($i = 0; $i < $n; $i++) {
$param_type .= $this->paramTypeArray[$i];
}
$a_params[] = & $param_type;
for($i = 0; $i < $n; $i++) {
$a_bind_params[] = $this->paramBindArray[$i];
}
for($i = 0; $i < $n; $i++) {
$a_params[] = & $a_bind_params[$i];
}
$q = "delete from ".$t." where ".$c;
$s = $this->MYSQLI_LINK->prepare($q);
$this->last_query = $q;
if($s === false) {
trigger_error('Wrong SQL: ' . $q . ' Error: ' . $this->MYSQLI_LINK->errno . ' ' . $this->MYSQLI_LINK->error, E_USER_ERROR);
}
call_user_func_array(array($s, 'bind_param'), $a_params);
$s->execute();
$count = $s->affected_rows;
$s->close();
if ($count > 0) {
$this->rows = $count;
return TRUE;
} else {
$this->last_error = mysqli_error($this->MYSQLI_LINK);
return FALSE;
}
}
public function insert($t, $d) {
$a_params = array();
$param_type = '';
$n = count($this->paramTypeArray);
for($i = 0; $i < $n; $i++) {
$param_type .= $this->paramTypeArray[$i];
}
$a_params[] = & $param_type;
for($i = 0; $i < $n; $i++) {
$a_bind_params[] = $this->paramBindArray[$i];
}
for($i = 0; $i < $n; $i++) {
$a_params[] = & $a_bind_params[$i];
}
$query_cols = 'insert into '.$t.' (';
$query_vals = 'values (';
while (list($key, $value) = each($d)) {
$query_cols .= $value . ', ';
$query_vals .= '?, ';
}
$query_cols = substr($query_cols, 0, strlen($query_cols) - 2);
$query_vals = substr($query_vals, 0, strlen($query_vals) - 2);
$q = $query_cols . ') ' . $query_vals . ')';
$this->last_query = $q;
$s = $this->MYSQLI_LINK->prepare($q);
if($s === false) {
trigger_error('Wrong SQL: ' . $q . ' Error: ' . $this->MYSQLI_LINK->errno . ' ' . $this->MYSQLI_LINK->error, E_USER_ERROR);
}
call_user_func_array(array($s, 'bind_param'), $a_params);
$s->execute();
$count = $s->affected_rows;
$this->last_id = $s->insert_id;
$s->close();
if ($count > 0) {
$this->rows = $count;
return TRUE;
} else {
$this->last_error = mysqli_error($this->MYSQLI_LINK);
return FALSE;
}
}
public function update($t, $d, $c) {
$a_params = array();
$param_type = '';
$n = count($this->paramTypeArray);
for($i = 0; $i < $n; $i++) {
$param_type .= $this->paramTypeArray[$i];
}
$a_params[] = & $param_type;
for($i = 0; $i < $n; $i++) {
$a_bind_params[] = $this->paramBindArray[$i];
}
for($i = 0; $i < $n; $i++) {
$a_params[] = & $a_bind_params[$i];
}
$q = 'update ' . $t . ' set ';
while (list($key, $value) = each($d)) {
$q .= $value . ' = ?, ';
}
//strip comma off end of variable
$q = substr($q, 0, strlen($q) - 2);
$q .= ' where ' . $c;
$this->last_query = $q;
$s = $this->MYSQLI_LINK->prepare($q);
if($s === false) {
trigger_error('Wrong SQL: ' . $q . ' Error: ' . $this->MYSQLI_LINK->errno . ' ' . $this->MYSQLI_LINK->error, E_USER_ERROR);
}
call_user_func_array(array($s, 'bind_param'), $a_params);
$s->execute();
$count = $s->affected_rows;
$s->close();
if ($count > 0) {
$this->rows = $count;
return TRUE;
} else {
$this->last_error = mysqli_error($this->MYSQLI_LINK);
return FALSE;
}
}
} // End Class
Simplified Schema
NOTE: Let me know if you need me to post a more complete schema. This just shows the fields that are linking the joins. All fields are INT(255) unique, id fields are INT(255) AI PRIMARY
SlipMaster links to SlipMain via slipCode, all others link foreign key
to Primary id
SlipMaster (id, slipCode)
SlipMain (id, slipCode, slipContractId, slipClientId, slipVesselId)
ContractMain (id, contractPaymentId)
ClientMain (id)
PaymentMain (id)
VesselMain (id)
* is all the fields in all the tables you are JOINing together. This includes duplicates, such as slipCode, which exists at least twice.
Plan A: Spell out the fields that you really want. This will make it easier to count them and know how many to "bind". And it will make it clear what order to bind them in.
Plan B: Don't use bind_result; simply fetch the result into an array or hash.
Plan C: Do both. (I prefer this.)
#Notorious, I think the answer to your problem is not the sql but to the bind_result() function that you are using.
Explaining furthur, the bind_result() function is used to assign retrieved data from the database to variables. So the number of fields selected (returned from the database) must be equal to the number of binded results.
For instance,
If I selected the firstname and the lastname fields from the database I must use
bind_result($firstname, $lastname);
So as you can see the number of variables in the bind_result() is equal to the number of fields selected.
For your case you are selecting everything from the first db to second to third ..blablabla till the last db. So make sure the number of fields assigned to the the bind_result() function is equal to the number of all the fields returned. That is the sum of the total number of columns in all the databases.
So you got a lot of typing to do but at least its for the best.
Good luck and I hope it helped.
Related
PHP experience system // simple
As a begginer in php programming language i'm playing with the code, working on localhost and i did some little projects.Now i am trying to do an experience system as simple as i can, i am stuck at this part and i don't know what i am doing wrong.Some suggestions? What i am doing wrong? The code. function update_user_xp($user_id, $xp_ammount){ global $db; $params = array('user_id' => $user_id); $users = $db->rawQuery("SELECT * FROM users_xp WHERE user_id = ?", $params); $data = array( 'user_xp_amount' => $xp_ammount + $users[0]['user_xp_amount'], 'user_id' => $user_id ); $db->where ('user_id', $data['user_id']); if ($db->update ('users_xp', $data)){ $xpReceived = 'You have received '.$xp_ammount.' points of experience! Have a total of '.$data['user_xp_amount'].' points of experience.'; } else { $xpReceived = $db->getLastError(); } return $xpReceived; } //update_user_xp(4, 10); // user_id: 4, update with 10 points function get_user_xp ($user_id){ global $db; $params = array('user_id' => $user_id); $user = $db->rawQueryOne ('SELECT * FROM users_xp WHERE user_id=?', $params); $xp = $user['user_xp_amount']; return $xp; } function xp_need () { global $db; $xpBarNeed = $db->rawQuery("SELECT `level`, `expneeded` FROM `experience_level`"); foreach ($xpBarNeed as $key => $value) { $output[] = $value; } return $output; } $xpn = xp_need(); $userXP = get_user_xp(4); for($i = 0; $i < count($xpn); $i++){ if($xpn[$i]['expneeded'] == $userXP) { //This part is working well print 'You are level <b>' . $xpn[$i]['level'].'</b>'; } else { if ($userXP > $xpn[$i]['expneeded'] && $userXP >= $xpn[$i]['expneeded']) { //This is the part that doesn t work, $diffEXP = $xpn[$i]['expneeded'] -= $userXP; print 'You need more exp '. $diffEXP.'</br>'; } } } This is how i am seeing in the page. https://prnt.sc/u7z18u
Please note that my solution is not the best or say a well-optimized solution at the time of writing. I will try to optimize it in the near future. For the time being, you can use this: <?php $xpn = xp_need(); $userXP = get_user_xp(4); $level = 0; $nextExp = 0; for ($i = count($xpn) - 1;$i >= 0;$i--) { if ($userXP >= $xpn[$i]['expneeded']) { $level = $xpn[$i]['level']; $nextExp = $xpn[$i + 1]['expneeded']; break; } } $expNeeded = $nextExp - $userXP; $percentage = round(($userXP/$nextExp) * 100); echo "Current level: " . $level; echo "<br/>Exp needed for the next level (" . ($level + 1) . "): " . $expNeeded; echo "<br/>Exp achieved percentage for the next level: " . $percentage; ?>
Printing prime numbers from an user's input php
I'm trying ta make a program that will ask the user for a number and then show all the prime numbers between 0 to this number in an array. <?php class SmallerPrimes{ public function __construct($file){ $this->input_filename = $file; } public function Main(){ $smaller_than = (int)$this->readString()[0]; $result = array(); /* YOUR CODE HERE */ function isPrime($n) { if ($n <= 1) return false; for ($i = 2; $i < $n; $i++) if ($n % $i == 0) return false; return true; } function printPrime($n) { for ($i = 2; $i <= $n; $i++) { if (isPrime($i)) echo $i . " "; } } $n = 7; printPrime($n); /*end of your code here */ return $result; } public function readString(){ $file = fopen($this->input_filename, "r"); $line = array(); while (!feof($file)){ array_push($line, str_replace(PHP_EOL, "", fgets($file))); } return $line; } } $o = new SmallerPrimes($argv[1]); echo implode(" ", $o->Main()) . PHP_EOL; This code work, but with a $n fixed. I don't know how to use an input who ask the user a number It's a code who verify itself and show us when it's ok The code that i have to complete is this one (we only have this at first): class SmallerPrimes{ public function __construct($file){ $this->input_filename = $file; } public function Main(){ $smaller_than = (int)$this->readString()[0]; $result = array(); /* YOUR CODE HERE */ return $result; } public function readString(){ $file = fopen($this->input_filename, "r"); $line = array(); while (!feof($file)){ array_push($line, str_replace(PHP_EOL, "", fgets($file))); } return $line; } } $o = new SmallerPrimes($argv[1]); echo implode(" ", $o->Main()) . PHP_EOL;
This is your script: <?php class SmallerPrimes{ public function __construct($file){ $this->input_filename = $file; } public function Main(){ $smaller_than = (int)$this->readString()[0]; $result = array(); function isPrime($n) { if ($n <= 1) return false; for ($i = 2; $i < $n; $i++) if ($n % $i == 0) return false; return true; } function printPrime($n) { for ($i = 2; $i < $n; $i++) if (isPrime($i)) $result[] = $i; return $result; } $result = printPrime($smaller_than); return $result; } public function readString(){ $file = fopen($this->input_filename, "r"); $line = array(); while (!feof($file)){ array_push($line, str_replace(PHP_EOL, "", fgets($file))); } return $line; }} $o = new SmallerPrimes($argv[1]); echo implode(" ", $o->Main()) . PHP_EOL;
function getSmallerPrimes($smaller_than) { if ($smaller_than <= 2) { return []; } $result = [2]; $sqrt = sqrt($smaller_than); for ($n = 3; $n < $smaller_than; $n += 2) { $isPrime = true; foreach($result as $prime) { if ($n % $prime == 0) { $isPrime = false; break; } if ($prime > $sqrt) { break; } } if ($isPrime) { $result[] = $n; } } return $result; } $input = 23; echo implode(' ', getSmallerPrimes($input)); Result: 2 3 5 7 11 13 17 19
PHP Simple object oriented application
I am getting undefined variable for periods and subPeriods on the last line of this program. not sure what the problem is. Could it be my instances? This is my first proper attempt at oop in PHP so i am sure i am doing something wrong. $global_periods = 5; $global_subperiods = 2; $questionslist = array("q_1_1", "q_1_2", "q_2_1", "q_2_2", "q_3_1", "q_4_1", "q_5_1"); class User { public $userId; public $periods = array(); public function __construct($number) { $this->userId = $number; } public function addPeriod($pno) { $periods[] = new Period($pno); } } class Period { public $periodNo; public $subPeriods = array(); public function __construct($number) { $this->periodNo = $number; } public function addSubPeriod($spno) { $subPeriods[] = new SubPeriod($spno); } } class SubPeriod { public $SubPeriodNo; public $answers = array(); public function __construct($number) { $this->SubPeriodNo = $number; } public function addAnswer($answer) { $answers[] = new Answer($answer); } } class Question { public $answer; public function __construct($ans) { $this->answer = $ans; } public function getAnswer() { echo $answer; } } $userlist = array(); $sql = 'SELECT user_ref FROM _survey_1_as GROUP BY user_ref ORDER BY user_ref ASC'; $result = mysql_query($sql); while ($row = mysql_fetch_array($result)) { $userlist[] = new User($row['user_ref']); } for ($i = 0; $i >= count($userlist); $i++) { for ($x = 1; $x > $global_periods; $x++) { $userlist[i]->addPeriod($x); for ($y = 1; $y > $global_subperiods; $y++) { $userlist[i]->$periods[x]->addSubPeriod($y); foreach($questionslist as $aquestion) { $sql = 'SELECT ' . $questionNumber . ' FROM _survey_1_as WHERE user_ref = ' . $i . ' AND answer_sub_period = ' . $y . ' AND answer_period = ' . $x .''; $result = mysql_query($sql); while ($row = mysql_fetch_array($result)) { $userlist[i]->$periods[x]->$subPeriods[y]->addAnswer($row[$questionNumber]); } } } } } $userlist[3]->$periods[2]->$subPeriods[2]->getAnswer();
Remove all the $ signs behind the $userlist, you only need to define the first variable. You can't use dollar signs like this, this way, it will try get the value of the word after the $ sign and call that, but that variable doesn't exist.
prepared statements - creating a single method*
FYI. ended up going with PDO solution as this was simpler. I'm trying to add a single method to handle all queries to the database. I want the queries to use parameter binding. How do I handle a variable amount of function parameters in mysqli_stmt_bind_param()? This post here led me to understand the pros of parameter binding. Here is my example code..where I am currently stuck at is marked. INPUT PARAMETERS $query = "INSERT INTO b0 VALUES (?, ?, ?)" $par_arr = {'bookmark', 'http://www.bookmark.com', 'tag'} PROTOTYPE CODE protected static function query($query, $par_arr) { if($statement=mysqli_prepare(one::$db, $query) { mysqli_stmt_bind_param($statement, "s", ...variable amount of parameters...);<----how should this be handled? ...
Update 2: If you experience any further problems with this code, then you should probably follow this advice and use PDO instead. This is how you should be using call_user_func_array [docs]: protected static function query($query, $types, $values) { if($statement = mysqli_prepare(one::$db, $query) { $parameters = array_merge(array($statement, $types), $values); call_user_func_array('mysqli_stmt_bind_param', $parameters); // ... } } where $types is a string indicating the type of each value, as described in the mysqli_stmt_bind_param documentation (call_user_func_array is even mentioned there). Update: It seems it is not that easy after all, and you have to create references to the values first: foreach($values as $k => $v) { $values[$k] = &$v; } $parameters = array_merge(array($statement, $types), $values); call_user_func_array('mysqli_stmt_bind_param', $parameters); // ... call_user_func_array is for user defined functions per php.net No it's not. The first parameter is of type callback, and the documentation says (emphasis mine): A PHP function is passed by its name as a string. Any built-in or user-defined function can be used, except language constructs such as: array(), echo(), empty(), eval(), exit(), isset(), list(), print() or unset(). Next remark: is just used to simplify syntax for passing arrays to user defined functions Have you had a look at the examples? Each element of the array you pass to call_user_func_array will be passed as argument to the function you specify. Arrays are the only way to have a collection of values of variable size.
Because i find prepared statements boring, I am processing placeholders manually, and experience not a single problem of yours private function prepareQuery($args) { $raw = $query = array_shift($args); preg_match_all('~(\?[a-z?])~',$query,$m,PREG_OFFSET_CAPTURE); $pholders = $m[1]; $count = 0; foreach ($pholders as $i => $p) { if ($p[0] != '??') { $count++; } } if ( $count != count($args) ) { throw new E_DB_MySQL_parser("Number of args (".count($args).") doesn't match number of placeholders ($count) in [$raw]"); } $shift = 0; $qmarks = 0; foreach ($pholders as $i => $p) { $pholder = $p[0]; $offset = $p[1] + $shift; if ($pholder != '??') { $value = $args[$i-$qmarks]; } switch ($pholder) { case '?n': $value = $this->escapeIdent($value); break; case '?s': $value = $this->escapeString($value); break; case '?i': $value = $this->escapeInt($value); break; case '?a': $value = $this->createIN($value); break; case '?u': $value = $this->createSET($value); break; case '??': $value = '?'; $qmarks++; break; default: throw new E_DB_MySQL_parser("Unknown placeholder type ($pholder) in [$raw]"); } $query = substr_replace($query,$value,$offset,2); $shift+= strlen($value) - strlen($pholder); } $this->lastquery = $query; return $query; } and thus an insert query can be called as simple as $db->run("INSERT INTO table SET ?u",$data);
I have added the complete code to create a single method for select prepared statement and insert prepared statement, Please follow the instruction and read all the comments. create database with the name 'test' and add the following query to create "users" table in the CREATE TABLE IF NOT EXISTS `users` ( `users_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `first_name` varchar(100) NOT NULL, `last_name` varchar(100) NOT NULL, PRIMARY KEY (`users_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ; INSERT INTO `users` (`users_id`, `first_name`, `last_name`) VALUES (1, 'daniel', 'martin'), (2, 'daniel', 'martin'); <?php error_reporting(E_ALL); ini_set('display_errors',1); session_start(); class mysqli_access extends mysqli{ private $ip1; private $dbconn; private $hostname = HST; // hostname private $username = USR; // username private $password = PWD; // password private $dbname = DBN; // datbase name function mysqli_access() { $ip= $_SERVER['REMOTE_ADDR']; $ip1="ip_".str_replace('.', "", $ip); if(!is_resource($_SESSION[$ip1])) { $this->dbconn = new mysqli($this->hostname,$this->username,$this->password,$this->dbname); $_SESSION[$ip1] = $this->dbconn; $dbconn = $this->dbconn; if( $this->connect_error ) { $this->Display_error('', $this->connect_errno, $this->connect_error, __FUNCTION__); } } else { $this->dbconn = $_SESSION[$ip1]; // success } return $this->dbconn; } function SelectPrepared($sql,$types,$params,$rows = '') { $results = array(); if ($stmt = $this->dbconn->prepare($sql)) { if($types&&$params) { $bind_names[] = $types; for ($i=0; $i<count($params);$i++) { $bind_name = 'bind' . $i; $$bind_name = $params[$i]; $bind_names[] = &$$bind_name; } $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); } $stmt->execute(); /* execute query */ $meta = $stmt->result_metadata(); while ($field = $meta->fetch_field()) { $var = $field->name; $$var = null; $fields_arr[$var] = &$$var; } call_user_func_array(array($stmt,'bind_result'),$fields_arr); if($rows == 1){ while ($stmt->fetch()) { $results = array(); foreach($fields_arr as $k => $v) $results[$k] = $v; } }else{ $i = 0; while ($stmt->fetch()) { $results[$i] = array(); foreach($fields_arr as $k => $v) $results[$i][$k] = $v; $i++; } } return $results; } } public function InsertPrepared($tblName,$arrFieldNameValue,$replace_flag=0){ $TableName = $tblName; if($replace_flag==0) { $sqlFirst ="INSERT INTO " . $TableName . "("; } if($replace_flag==1) { $sqlFirst ="INSERT IGNORE INTO " . $TableName . "("; } if($replace_flag==2) { $sqlFirst ="REPLACE INTO " . $TableName . "("; } $sqlSecond =" values("; $params = array(); $types = ''; while(list($key,$value) = each($arrFieldNameValue)) { $sqlFirst = $sqlFirst . $key . ","; $sqlSecond = $sqlSecond . '?' . ","; $params[] = $value; $types = $types . $this->GetValType($value); } $sqlFirst = substr($sqlFirst,0,strlen($sqlFirst)-1) . ") "; $sqlSecond = substr($sqlSecond,0,strlen($sqlSecond)-1) .")"; $sql = $sqlFirst . $sqlSecond; if ($stmt = $this->dbconn->prepare($sql)) { if($types&&$params) { $bind_names[] = $types; for ($i=0; $i<count($params);$i++) { $bind_name = 'bind' . $i; $$bind_name = $params[$i]; $bind_names[] = &$$bind_name; } $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); } $stmt->execute(); /* execute query */ } return mysqli_insert_id($this->dbconn); } private function GetValType($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 's'; } } class Model_NAME extends mysqli_access { function Model_NAME() { $this->tablename = TABLENAME; $this->mysqli_access(); } ##---------------------------- Custom function start from here -----------------# ## fetch settings values function getUserRow($id,$key) { $sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE first_name=? and users_id = ?"; $param = "si"; $array_of_params[] = addslashes($key); $array_of_params[] = addslashes($id); $result= $this->SelectPrepared($sql,$param,$array_of_params,1); //last parameter 1 use if want fetch single row , other wise function will return multi dimensional array return $result; } ## fetch settings values function getUserRows($last_name) { $sql ="SELECT first_name,last_name FROM ".$this->tablename." WHERE last_name= ?"; $param = "s"; $array_of_params[] = addslashes($last_name); $result= $this->SelectPrepared($sql,$param,$array_of_params); //last parameter 1 use if want fetch single row , other wise function will return multi dimensional array return $result; } function addValue($Array) { return $this->InsertPrepared( $this->tablename , $Array); } } // configuration define('HST','localhost'); define('USR','root'); define('PWD','techmodi'); define('DBN','test'); define('TABLENAME','users'); $obj = new Model_NAME(); $arr = array(); $arr['first_name'] = addslashes("daniel"); $arr['last_name'] = addslashes("martin"); $obj->addValue($arr); // for insert records // after inserting get the records $singleRow = $obj->getUserRow(1,'daniel'); // for select single records $multiRow =$obj->getUserRows('martin'); // for select records echo '<pre>'; echo '<br/>-------- Single Records -----------------<br/>'; print_r($singleRow); echo '<br/>-------- Multiple Records-----------------<br/>'; print_r($multiRow); ?>
PHP PDO function, Looking for some suggestions
I am by no means asking for anyone to re-write my code, but rather find places where I can improve it, or implement better practices. This is how the function briefly works. Function $Class->getTaxClass() accepts a minimum of 1 argument, which can either be a single ID, or an array of ID's. It can also than accept values for specific rows which it wants to grab like such $Class->getTaxClass($array, 'name','tid') So I am really just looking for ways to improve the code structure / best practices / logic of the function, which is as follows: public function getTaxClass() { $arg = func_get_args(); $or = 'pa.pid = ?'; if(is_array($arg[0])) { $i = 1; while($i < count($arg[0])) { $or .= " OR pa.pid = ?"; $i ++; } } if(count($arg) == 1) { $pid = $arg[0]; $row = "a.*"; } else if(count($arg > 1)) { $pid = array_shift($arg); $prepared_args = array(); foreach($arg as $a) { $prepared_args[] = "a." . $a; } $row = implode(',', $prepared_args); } $stmt = _DB::init()->prepare("SELECT $row FROM tax_class a INNER JOIN products_to_tax_class pa ON a.tid = pa.tid WHERE ($or)" ); if(is_array($arg[0])) { if($stmt->execute($arg[0])) return $stmt->fetch(PDO::FETCH_ASSOC); } else { if($stmt->execute(array($pid))) return $stmt->fetch(PDO::FETCH_ASSOC); } } Much appreciated!
My suggestion: public function getTaxClass() { $args = func_get_args(); // columns to select: $cols = array(); for ($i=1; $i<=count($args); $i++) { $cols[] = "a.{$args[$i]}"; } $cols = count($cols) ? join(',', $cols) : 'a.*'; // IDs to filter and their placeholders: $ids = (array) $args[0]; $phs = join(',', array_fill(0, count($ids), '?')); $stmt = _DB::init()->prepare( "SELECT {$cols} FROM tax_class a INNER JOIN products_to_tax_class pa ON a.tid = pa.tid WHERE pa.pid IN ({$phs})" ); if ($stmt->execute($ids)) { return $stmt->fetch(PDO::FETCH_ASSOC); } } P.S. code is untested, some errors may still occur :)