I have created a Database Abstraction Layer over PDO to refrain from creating multiple queries around my scripts which would be pretty hard to maintain.
My DBAL is not very broad; It takes care of simple tasks such as INSERTING, UPDATING and SELECTING (with or without joining). It does not cover more advanced stuff such as selecting from multiple tables etc.
The problem that raised with my DBAL is that it is confusing queries when there are more of the same type in one HTTP request. For example there are three select statements in my script, the first one works, the other two don't. I tried creating a flush method to clear the previously filled attributes by the query, but it's not working and I'm out of ideas. I'm not ready to get rid of my class and get back to writing queries all over - it's so easy to write them this way.
Anyway, this is how I do some queries with my class:
$insert_update_select = array(
'COLUMNS' => array(
'column_name1' => 'data_to_update_or_insert1',
'column_name2' => 'data_to_update_or_insert2'
),
'WHERE' => array('x > y', 'y < x'),
'ORDER' => array('ASC' => 'column_name1'),
'LIMIT' => array(0, 5),
);
// This query works with updating, inserting and selecting
$db = new db();
$db->insert('table_name', $insert_update_select);
$db->update('table_name', $insert_update_select);
$db->select('table_name', $insert_update_select);
Don't ask me how to join tables; I actually forgot how my own syntax works for that, haha. (Gotta try to remember)
Anyway, here is my class:
<?php
class db
{
private $db_type = 'mysql';
private $db_host = 'localhost';
private $db_user = 'root';
private $db_pass = '';
private $db_name = 'imgzer';
private $db;
private $db_connection = '';
private $insert_data = '';
private $update_data = '';
private $select_data = '';
private $condition_data = '';
private $order_data = '';
private $limit_data = '';
private $join_data = array();
private $query;
private $table;
private $return_data;
private $affected_rows;
private $return_id;
// Database tables
const USERS_TABLE = 'imgzer_users';
const CONFIG_TABLE = 'imgzer_config';
public function __construct()
{
$this->db_connection = "$this->db_type:host=$this->db_host;dbname=$this->db_name";
$this->db = new PDO($this->db_connection, $this->db_user, $this->db_pass);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
unset($this->db_pass);
}
public function open()
{
if ($this->db)
{
return true;
}
return false;
}
public function close()
{
if ($this->db->close())
{
return true;
}
return false;
}
private function build_array($type, $data, $join_data = array())
{
if (empty($data))
{
return;
}
$type = strtoupper($type);
$this->update_data = '';
$this->select_data = '';
$data_index = 0;
$data_length = sizeof($data);
$last_row = $data_length - 1;
switch ($type)
{
case 'INSERT':
if (!is_array($data))
{
return;
}
$this->insert_data = '(';
foreach ($data as $column => $value)
{
$this->insert_data .= $column . (($data_index != $last_row) ? ', ' : '');
$data_index++;
}
$data_index = 0;
$this->insert_data .= ') ';
$this->insert_data .= 'VALUES (';
foreach ($data as $column => $value)
{
$this->insert_data .= '?' . (($data_index != $last_row) ? ', ' : '');
$data_index++;
}
$this->insert_data .= ') ';
break;
case 'UPDATE':
$this->update_data = '';
foreach ($data as $column => $value)
{
$this->update_data .= $column . ' = ?' . (($data_index != $last_row) ? ', ' : '');
$data_index++;
}
break;
case 'SELECT':
if (empty($join_data))
{
return;
}
if (is_array($join_data))
{
$from_table = array_keys($join_data['FROM']);
$join_table = array_keys($join_data['TABLES']);
$this->select_data = implode(', ', array_flip($data)) . ' FROM ' ;
$this->select_data .= $from_table[0] . ' ' . $join_data['FROM'][$from_table[0]] . ' ';
for ($i = 0; $i < sizeof($this->join_data); $i++)
{
$this->select_data .= $this->get_join_type($join_data['JOIN']). ' ';
$this->select_data .= $join_table[$i] . ' ' . $join_data['TABLES'][$join_table[$i]];
$this->select_data .= $this->join_data[$i];
}
$this->select_data = rtrim($this->select_data, ' ');
}
else
{
if (!isset($data[0]))
{
$data = array_flip($data);
}
$this->select_data = implode(', ', $data) . ' FROM ' . $this->table . ' ';
}
break;
}
}
private function set_join($on)
{
if (empty($on))
{
return;
}
if (is_array($on))
{
for ($i = 0; $i < sizeof($on); $i++)
{
$on[$i] = ' ON (' . implode(' AND ', $on[$i]) . ') ';
}
}
$this->join_data = $on;
}
private function set_order($order)
{
if (empty($order))
{
return;
}
$this->order_data = ' ORDER BY ';
if (is_array($order))
{
$data_index = 0;
$data_size = sizeof($order) - 1;
foreach ($order as $order_type => $column)
{
if ($order_type != 'ASC' && $order_type != 'DESC')
{
throw new Exception('Order type in SQL has to be either ASC or DESC');
return;
}
$this->order_data .= $column . ' ' . $order_type . (($data_index != $data_size) ? ', ' : '');
$data_index++;
}
return;
}
$this->order_data .= $order;
}
private function set_limit($limit)
{
if (empty($limit))
{
return;
}
if (sizeof($limit) > 2)
{
return;
}
if (sizeof($limit) == 1)
{
$limit = array(0, $limit[0]);
}
if (is_array($limit))
{
$limit = implode(', ', $limit);
}
$this->limit_data = " LIMIT {$limit}";
}
private function set_where($condition)
{
if (empty($condition))
{
return;
}
if (is_array($condition))
{
$condition = implode(' AND ', $condition);
}
$this->condition_data = " WHERE $condition";
}
public function in_set($where_ary)
{
$where_str = implode(', ', $where_ary);
$where_str = substr($where_str, 0, -2);
$where_str = 'IN (' . $where_str . ')';
return $where_str;
}
/*
* Example usage:
* $insert_ary = array('col_1' => 'col_data_1', 'col_2' => 'col_data_2');
* $condition_ary = array('col_1 > 5', 'col_2 <> 10');
* $order_ary = array('ASC' => 'col_1', 'DESC' => 'col_2');
* $limit = array($start = 0, $limit = 5);
* $instance->insert('my_table', $insert_ary, $condition_ary, $order_ary, $limit);
*/
public function insert($table, $data, $return_id = false)
{
$data = $this->data_abstract($data);
// Prepare the arrays
$this->build_array('INSERT', $data['COLUMNS']);
$this->set_where($data['WHERE']);
$this->set_order($data['ORDER']);
$this->set_limit($data['LIMIT']);
$sql = 'INSERT INTO ' . $table . ' ';
$sql .= $this->insert_data;
$sql .= $this->condition_data;
$sql .= $this->order_data;
$sql .= $this->limit_data;
$this->query = $this->db->prepare($sql);
$param_index = 1;
foreach ($data['COLUMNS'] as $column => &$value)
{
$this->query->bindParam($param_index, $value);
$param_index++;
}
$this->query->execute();
if ($return_id)
{
$this->return_id = $this->query->last_insert_id();
}
else
{
$this->affected_rows = $this->query->rowCount();
}
}
public function update($table, $data, $return_id = false)
{
$data = $this->data_abstract($data);
// Prepare the arrays
$this->build_array('UPDATE', $data['COLUMNS']);
$this->set_where($data['WHERE']);
$this->set_order($data['ORDER']);
$this->set_limit($data['LIMIT']);
$sql = 'UPDATE ' . $table . ' SET ';
$sql .= $this->update_data;
$sql .= $this->condition_data;
$sql .= $this->order_data;
$sql .= $this->limit_data;
$this->query = $this->db->prepare($sql);
$param_index = 1;
foreach ($data['COLUMNS'] as $column => &$value)
{
$this->query->bindParam($param_index, $value);
$param_index++;
}
$this->query->execute();
if ($return_data)
{
$this->return_id = $this->query->last_insert_id();
}
else
{
$this->affected_rows = $this->query->rowCount();
}
}
/*
* Joining example:
* $join_data = array(
* 'TABLES' => array('table_2' => 't2', 'table_3' => 't3'),
* 'JOIN' => 'LEFT',
* 'ON' => array(
* array('colx > 15', 'coly < 20'),
* array('fieldx > 15', 'fieldy < 20')
* ),
*);
*/
public function select($table, $data, $join = false, $fetch_type = 'assoc')
{
$data = $this->data_abstract($data);
if ($join)
{
if (!is_array($table))
{
throw new Exception('Table has to be associated with a short index');
return;
}
$this->set_join($join['ON']);
$table = array_merge(array('FROM' => $table), $join);
}
// Globalize table name if not joins are used
$this->table = $table;
// Prepare the arrays
$this->build_array('SELECT', $data['COLUMNS'], $table);
$this->set_where($data['WHERE']);
$this->set_order($data['ORDER']);
$this->set_limit($data['LIMIT']);
$sql = 'SELECT ';
$sql .= $this->select_data;
$sql .= $this->condition_data;
$sql .= $this->order_data;
$sql .= $this->limit_data;
$this->query = $this->db->prepare($sql);
$result = $this->query->execute();
$fetch_type = ($fetch_type == 'assoc') ? PDO::FETCH_ASSOC : PDO::FETCH_NUM;
$fetched_data = $this->query->fetchAll($fetch_type);
$data_result = $fetched_data;
if (sizeof($fetched_data) == 1)
{
$data_result = $fetched_data[0];
}
$this->return_data = $data_result;
// Clear the result
//$this->query->closeCursor();
}
public function fetch()
{
return $this->return_data;
}
public function affected_rows()
{
return $this->affected_rows;
}
private function data_abstract($data)
{
$abstract_ary = array('COLUMNS' => '', 'WHERE' => '', 'ORDER' => '', 'LIMIT' => 0);
return array_merge($abstract_ary, $data);
}
private function get_join_type($type)
{
switch ($type)
{
default:
case 'LEFT':
return 'LEFT JOIN';
break;
case 'RIGHT':
return 'RIGHT JOIN';
break;
case 'INNER':
return 'INNER JOIN';
break;
case 'NORMAL':
case 'JOIN':
return 'JOIN';
break;
}
}
private function flush()
{
unset($this->query, $this->insert_data, $this->update_data, $this->select_data);
}
}
$db = new db();
?>
What's wrong with it (could be a lot) and how do I actually make it work efficiently?
Don't make it stateful.
Even without looking at the code I'll tell you what's the problem: get rid of $this->stmt variable.
For some reason, all the DBAL writers have strong inclination to such a variable... introducing state to their class and thus making it unusable.
All the method calls have to be atomic, each performing all the necessary operations and returning all the requested data. While saving nothing in the class variables. As simple as that. In such a rare case when PDOStatement object have to be used further - return this very object, don't save it inside. Otherwise just return the requested data.
I wold also advise to get rid of your whole DBAL, as it's written out of good intentions but I can tell for sure that implementation turns out to be less helpful but it actually makes your code worse in many aspects - readability, flexibility, maintainability. In pursue for the fictional usability, you are saving yourself only a word or two from SQL, but making whole application code unreliable.
You won't listen to me, though. Some experience in maintaining applications is required to see my point.
Related
What is the problem to the code? I cannot upload to database. It comes the message:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ACQUA'))' at line 2
query was:
SELECT `vals`.*, `opt`.*
FROM `eav_attribute_option_value` AS `vals`
INNER JOIN `eav_attribute_option` AS `opt` ON opt.option_id = vals.option_id
WHERE (opt.attribute_id='191')
AND (vals.value in ('ALESSANDRO DELL'ACQUA'))
PHP Code:
<?php
/**
* Adapted by Christopher Shennan
* http://www.chrisshennan.com
*
* Date: 20/04/2011
*
* Adaptered from original post by Srinigenie
* Original Post - http://www.magentocommerce.com/boards/viewthread/9391/
*/
class Mage_Eav_Model_Import extends Mage_Eav_Model_Mysql4_Entity_Attribute {
private $fileName;
private $delimiter = '|';
private $enclosure = '"';
private function &getCsv() {
$file = fopen($this->fileName, "r");
while (!feof($file)) {
$csvArr[] = fgetcsv($file, 0, $this->delimiter, $this->enclosure);
}
fclose($file);
return $csvArr;
}
protected function populateOptionTable($attribId) {
echo "Upload Begin<br/>";
$fields = array();
$values = array(); // store id => values
$optionValues = array(); // option id => $values
$option = array('value' => $optionValues);
$updateOptionValId;
$values = null;
$row = null;
$disCounter = 0;
$optionTable = $this->getTable('attribute_option');
$optionValueTable = $this->getTable('attribute_option_value');
$write = $this->_getWriteAdapter();
$csvStoreArr = array();
// Get CSV into Array
$csv = & $this->getCsv();
$read = $this->_getReadAdapter();
// exit if the csv file is empty or if it contains only the headers
if (count($csv) < 1 or count($csv) == 1)
return;
$fields = $csv[0]; // get the field headers from first row of CSV
// get the store Ids
$stores = Mage::getModel('core/store')
->getResourceCollection()
->setLoadDefault(true)
->load();
// determine the stores for which option values are being uploaded for
foreach ($fields as $hdr) {
if ($hdr === 'position' || $hdr === 'isDefault' || $hdr === 'ERROR') {
continue;
}
foreach ($stores as $store) {
if ($store->getCode() === $hdr)
$csvStoreArr[$hdr] = $store->getId();
}
}
// start reading the option values - from row 1 (note that 0 represents headers)
for ($indx = 1; $indx < count($csv); $indx++) {
$values = null; // initialize to null
$row = $csv[$indx]; // get row
if (isset($row) && count($row) > 0) {
//escape the single quote
//$whereParam = $read->quote($row);
if (is_array($row))
$whereParam = '(\'' . implode($row, '\',\'') . '\')';
else if (strlen($row))
$whereParam = '(\'' . $row . '\')';
$select = $read->select()->from(array('vals' => $optionValueTable))
->join(array('opt' => $optionTable), 'opt.option_id=vals.option_id')
->where('opt.attribute_id=?', $attribId);
$select = $select
->where('vals.value in ' . $whereParam);
$optionValData = $read->fetchAll($select);
unset($select);
// get the option Id for this option
if (count($optionValData) > 0) {
$optionValDataRow = $optionValData[0];
$optionId = $optionValDataRow['option_id'];
} else
$optionId = null;
$intOptionId = (int) $optionId;
if (!$intOptionId) {
$data = array(
'attribute_id' => $attribId,
'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0,
);
try {
$write->insert($optionTable, $data);
$intOptionId = $write->lastInsertId();
} catch (Exception $e) {
Mage::log($e->getMessage());
}
} else {
$data = array(
'sort_order' => isset($option['order'][$optionId]) ? $option['order'][$optionId] : 0,
);
$write->update($optionTable, $data, $write->quoteInto('option_id=?', $intOptionId));
}
$colIndx = 0; //initialize row's column index
if (isset($row) && is_array($row) && count($row) > 0) {
foreach ($row as $optVal) {
if ($fields[$colIndx] !== 'position' || $fields[$colIndx] !== 'isDefault' || $fields[$colIndx] !== 'ERROR') {
$values[$csvStoreArr[$fields[$colIndx]]] = $optVal; // store id => option value
}
$colIndx++;
}
}
}
if (isset($values) && is_array($values) && count($values) > 0) {
foreach ($values as $storeId => $value) {
if (!empty($value) || strlen($value) > 0) {
$value = trim($value);
$data = array(
'option_id' => $intOptionId,
'store_id' => $storeId,
'value' => $value,
);
$optionValInsert = true;
$optionValUpdate = false;
foreach ($optionValData as $valData) {
if ((int) $valData['option_id'] === $intOptionId &&
(int) $valData['store_id'] === $storeId) {
$optionValInsert = false;
if (strcasecmp(trim($valData['value']), $value) !== 0) {
$optionValUpdate = true;
$updateOptionValId = $valData['value_id'];
}
break;
}
}
if ($optionValInsert) {
$write->insert($optionValueTable, $data);
Mage::log('Inserted Value -' . $value);
} else if ($optionValUpdate) {
$write->update($optionValueTable, $data, $write->quoteInto('option_id=?', $updateOptionValId));
Mage::log('Updated Value -' . $value);
}
}
}
}
$optionValues[$optionId] = $values;
if ($indx % 20 == 0) {
echo "" . $indx . ' - uploaded!!<br />';
Mage::log($indx . ' - attributes uploaded!!', null, $this->fileName . '.log');
}
}
echo "" . $indx . ' - uploaded!!<br />';
echo '<b> Attribute Upload Finished </b><br />';
$option['value'] = $optionValues;
return null;
}
/**
* Enter description here...
*
* #param Mage_Core_Model_Abstract $object
* #return Mage_Eav_Model_Mysql4_Entity_Attribute
*/
public function saveOptionValues($attributeId, $fn) {
$option = array();
$this->fileName = $fn;
echo '<strong>Importing Attributes</strong><br/><br/>Reading file contents - ' . $this->fileName . '<br />';
Mage::log("Upload Begin", null, $this->fileName . '.log');
// Step 1 -- Get attribute Id from attribute code
$atrribId = $attributeId; //569
// Step 2 Obtain the option values into an array
$option = $this->populateOptionTable($atrribId);
}
}
Error is because of single Quotes in the string : 'ALESSANDRO DELL'ACQUA.
SELECT vals., opt. FROM eav_attribute_option_value AS vals INNER JOIN
eav_attribute_option AS opt ON opt.option_id=vals.option_id WHERE
(opt.attribute_id='191') AND (vals.value in ('ALESSANDRO
DELL'ACQUA'))
Try using double quotes.
String Literals in MySQL [ https://dev.mysql.com/doc/refman/5.0/en/string-literals.html ]
' single quote is reserved character in MySQL and there are several ways to include quote characters within a string:
A "'" inside a string quoted with "'" may be written as ""''".
A """ inside a string quoted with """ may be written as """".
Precede the quote character by an escape character (""\").
A "'" inside a string quoted with """ needs no special treatment and
need not be doubled or escaped. In the same way, """ inside a string
quoted with "'" needs no special treatment.
To avoid this use PreparedStatement in PHP http://www.w3schools.com/php/php_mysql_prepared_statements.asp
In your query is should be like 'ALESSANDRO DELL''ACQUA' instead of 'ALESSANDRO DELL'ACQUA'
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.
Let me preface that I just started learning prepared statements so much of this might just be to much to grasp, but I want to try.
I am trying to make a dynamic create function within my DatabaseObject class. The function would take any number of values of potentially any number of the different allowed data types. Unfortunately nothing I have tried has worked. Here is the code.
public function create() {
$db = Database::getInstance();
$mysqli = $db->getConnection();
//array of escaped values of all types in the object
$attributes = $this->sanitized_attributes();
$check = $mysqli->stmt_init();
$paramType = array();
$types = ''; $bindParam = array(); $where = ''; $count = 0;
foreach($attributes as $key=>$val)
{
$types .= 'i';
$bindParam[] = '$p'.$count.'=$param["'.$key.'"]';
$where .= "$key = ? AND ";
$count++;
}
$sql_query = "INSERT INTO `".static::$table_name."` ";
$sql_query .= "VALUES (";
foreach ($attributes as $key => $value) {
$valueType = gettype($value);
if ($valueType == 'string') {
$sql_query .= "?,";
array_push($paramType, "s");
} else if ($valueType == 'integer') {
$sql_query .= "?,";
array_push($paramType, "i");
} else if ($valueType == 'double') {
$sql_query .= "?,";
array_push($paramType, "d");
} else {
$sql_query .= "?,";
array_push($paramType, "b");
}
}
$sql_query .= ")";
}
At this point I am completely lost as to what I am suppose to do.
I have gotten simple prepared statements to work, but this one is much more complicated and dynamic and I don't know if I handled the process up to this point correctly and what to do following the sql_query in order to get this to work. All the questions here have left me confused so maybe if I got guidance with my current code to see where i went wrong it will assist.
I appreciate your time.
public function create() {
$db = Database::getInstance();
$mysqli = $db->getConnection();
$attributes = $this->sanitized_attributes();
$tableName = static::$table_name;
$columnNames = array();
$placeHolders = array();
$values = array();
foreach($attributes as $key=>$val)
{
// skip identity field
if ($key == static::$identity)
continue;
$columnNames[] = '`' . $key. '`';
$placeHolders[] = '?';
$values[] = $val;
}
$sql = "Insert into `{$tableName}` (" . join(',', $columnNames) . ") VALUES (" . join(',', $placeHolders) . ")";
$statement = $mysqli->stmt_init();
if (!$statement->prepare($sql)) {
die("Error message: " . $mysqli->error);
return;
}
$bindString = array();
$bindValues = array();
// build bind mapping (ssdib) as an array
foreach($values as $value) {
$valueType = gettype($value);
if ($valueType == 'string') {
$bindString[] = 's';
} else if ($valueType == 'integer') {
$bindString[] = 'i';
} else if ($valueType == 'double') {
$bindString[] = 'd';
} else {
$bindString[] = 'b';
}
$bindValues[] = $value;
}
// prepend the bind mapping (ssdib) to the beginning of the array
array_unshift($bindValues, join('', $bindString));
// convert the array to an array of references
$bindReferences = array();
foreach($bindValues as $k => $v) {
$bindReferences[$k] = &$bindValues[$k];
}
// call the bind_param function passing the array of referenced values
call_user_func_array(array($statement, "bind_param"), $bindReferences);
$statement->execute();
$statement->close();
return true;
}
I want to make special note that I did not find the solution myself. I had a long time developer find this solution and wanted to post it for those that might want to know.
I accidently found your old post as I was trying myself to find a solution to the exact same problem. My code seems a bit more advantagous as there is only one loop included. Therefore I will add it as a possible improvement to this post:
$sqlquery = $this->MySQLiObj->prepare($dummy);
$paramQuery = array();
$paramQuery[0] = '';
$n = count($valueArray);
for($i = 0; $i < $n; $i++) {
$checkedDataType = $this->returnDataType($valueArray[$i]);
if($checkedkDataType==false) {
return false;
}
$paramQuery[0] .= $checkedDataType;
/* with call_user_func_array, array params must be passed by reference -> & */
$paramQuery[] = &$valueArray[$i];
}
/*In array(): sqlquery(object)->bind_param(method)*/
call_user_func_array(array($sqlquery, 'bind_param'), $paramQuery);
$sqlquery->execute();
/*Can be used identical to $result = $mysqli->query()*/
$result = $this->MySQLiObj->get_result();
$sqlquery->close();
Utilizing the function returnDataType() with a switch statement, which might be faster if there is a preference for a certain data type.
private function returnDataType($input) {
switch(gettype($input)) {
case string: return 's';
case double: return 'd';
case integer: return 'i';
default: $this->LOG->doLog("Unknown datatype during database access."); return 's';
}
}
I have a Love Factory extension in Joomla.
Love Factory 4.1.1
Joomla version 3.1
I extended interaction so the user can become a fan.
But when the JModelLegacy::getInstance (html.php) tries to get an Instance it crashed on require_once $path in legacy.php.
I tried to change only format in friends model and then it does not load it too.
It just take part of the code from required class and paste it on the screen. Example from friend.php
<?php
//class definition missing
//function definition missing
if (friendsLimitReached()) {
$this->setError(FactoryText::_('membership_restriction_error_friends_limit'));
$this->setState('membership_restriction_error', true);
return false;
}
// Load friendship request.
$table = $this->getTable('Friend');
$result = $table->load(array('sender_id' => $userId, 'receiver_id' => $user->id, 'pending' => 1));
// Check if friendship request was found.
if (!$result) {
$this->setError(FactoryText::_('friend_task_accept_error_request_not_found'));
return false;
}
// Check if it's relationship request and if users already have a relationship.
if (2 == $table->type && $this->usersInRelationship($user->id, $userId)) {
return false;
}
$table->accept();
return true;
}
public function reject($userId) {
// Initialise variables.
$user = JFactory::getUser();
// Load friendship request.
$table = $this->getTable('Friend');
$result = $table->load(array('sender_id' => $userId, 'receiver_id' => $user->id, 'pending' => 1));
// Check if friendship request was found.
if (!$result) {
$this->setError(FactoryText::_('friend_task_accept_error_request_not_found'));
return false;
}
$table->remove();
return true;
}
public function cancel($userId) {
$user = JFactory::getUser();
$table = $this->getTable('Friend');
$return = $table->load(array('sender_id' => $user->id, 'receiver_id' => $userId, 'type' => 1, 'pending' => 1));
// Check if request exists.
if (!$return) {
$this->setError(FactoryText::_('friend_task_cancel_error_request_not_found'));
return false;
}
if (!$table->delete()) {
$this->setError($table->getError());
return false;
}
return true;
}
public function request($userId) {
// Initialise variables.
$user = JFactory::getUser();
// Check friends limit
$model = JModelLegacy::getInstance('Friends', 'FrontendModel');
if ($model->friendsLimitReached()) {
$this->setError($model->getError());
$this->setState('membership_restriction_error', true);
return false;
}
// Check if sending request to self
if ($userId == $user->id) {
$this->setError(FactoryText::_('friend_taks_request_error_self_request'));
return false;
}
// Check if user is blacklisted
$model = JModelLegacy::getInstance('Blacklist', 'FrontendModel');
if ($model->isBlacklisted($user->id, $userId)) {
$this->setError($model->getError());
return false;
}
// Check if user is allowed to interact with members of same gender
$my_profile = $this->getTable('Profile', 'Table');
$profile = $this->getTable('Profile', 'Table');
$my_profile->loadAndMembership($user->id);
$profile->load($userId);
if (!$my_profile->membership_sold->same_gender_interaction && $my_profile->sex == $profile->sex) {
$this->setError(FactoryText::_('membership_restriction_error_same_gender_interaction'));
$this->setState('membership_restriction_error', true);
return false;
}
// Check if request already sent or friends already
$query = ' SELECT id' . ' FROM #__lovefactory_friends' . ' WHERE ((sender_id = ' . $userId . ' AND receiver_id = ' . $user->id . ')' . ' OR (sender_id = ' . $user->id . ' AND receiver_id = ' . $userId . '))' . ' AND type = 1';
$this->_db->setQuery($query);
$result = $this->_db->loadResult();
if ($result) {
$this->setError(FactoryText::_('friend_task_request_error_alredy_friends_or_pending'));
return false;
}
$message = JRequest::getVar('message', '', 'POST', 'string');
$friend = $this->getTable('Friend');
$friend->request($user->id, $userId, $message);
// Send notification
$mailer = FactoryMailer::getInstance();
$mailer->send( 'friend_request', $userId, array( JFactory::getUser($userId)->username, JFactory::getUser($user->id)->username, ) );
return true;
}
public function remove($userId) {
$friendship = $this->getFriendship($userId, 1);
if (!$friendship || 1 == $friendship->pending) {
$this->setError(FactoryText::_('friend task remove friend not found'));
return false;
}
$table = $this->getTable('Friend', 'Table');
$table->bind($friendship);
if (!$table->remove()) {
$this->setError($table->getError());
return false;
}
return true;
}
public function promote($mode, $userId) {
if ('promote' == $mode) {
return $this->promoteFriend($userId);
}
return $this->demoteFriend($userId);
}
public function getFriendshipStatus($firstUser, $secondUser, $type = 1) {
if (!$firstUser || ! $secondUser) {
return 0;
}
$dbo = $this->getDbo();
$query = $dbo->getQuery(true) ->select('f.*') ->from('#__lovefactory_friends f') ->where('((f.sender_id = ' . $dbo->quote($firstUser) . ' AND f.receiver_id = ' . $dbo->quote($secondUser) . ') OR (f.sender_id = ' . $dbo->quote($secondUser) . ' AND f.receiver_id = ' . $dbo->quote($firstUser) . '))') ->where('f.type = ' . $dbo->quote($type));
$result = $dbo->setQuery($query) ->loadObject();
if (!$result) {
return 0;
}
if ($result->pending) {
return $firstUser == $result->sender_id ? 2 : 3;
}
return 1;
}
protected function promoteFriend($userId) {
// Initialise variables.
$friendship = $this->getFriendship($userId);
$user = JFactory::getUser();
// Check if users are friends.
if (!$friendship || $friendship->pending == 1) {
$this->setError(FactoryText::_('friend_task_promote_friend_not_found'));
return false;
}
// Check if user is already a top friend.
if (($friendship->sender_id == $user->id && $friendship->sender_status) || ($friendship->receiver_id == $user->id && $friendship->receiver_status)) {
$this->setError(FactoryText::_('friend task promote already top friend'));
return false;
}
// Check if top friends limit is reached.
$friends = JModelLegacy::getInstance('Friends', 'FrontendModel');
if ($friends->friendsLimitReached(1)) {
$this->setError(FactoryText::_('friend task promote top friends limit reached'));
$this->setState('membership_restriction_error', true);
return false;
}
// Promote friend.
$table = $this->getTable('Friend', 'Table');
$table->id = $friendship->id;
if ($friendship->sender_id == $user->id) {
$table->sender_status = 1;
}
else {
$table->receiver_status = 1;
}
if (!$table->store()) {
$this->setError($table->getError());
return false;
}
return true;
}
protected function demoteFriend($userId) {
// Initialise variables.
$friendship = $this->getFriendship($userId);
$user = JFactory::getUser();
// Check if users are friends.
if (!$friendship || $friendship->pending == 1) {
$this->setError(FactoryText::_('friend_task_promote_friend_not_found'));
return false;
}
// Check if user is top friend.
if (($friendship->sender_id == $user->id && !$friendship->sender_status) || ($friendship->receiver_id == $user->id && !$friendship->receiver_status)) {
$this->setError(FactoryText::_('friend task demote not top friend'));
return false;
}
// Demote friend.
$table = $this->getTable('Friend', 'Table');
$table->id = $friendship->id;
if ($friendship->sender_id == $user->id) {
$table->sender_status = 0;
}
else {
$table->receiver_status = 0;
}
if (!$table->store()) {
$this->setError($table->getError());
return false;
}
return true;
}
public function getFriendship($userId, $type = 1) {
$user = JFactory::getUser();
$dbo = $this->getDbo();
$query = $dbo->getQuery(true) ->select('f.*') ->from('#__lovefactory_friends f') ->where('((f.sender_id = ' . $dbo->quote($userId) . ' AND f.receiver_id = ' . $dbo->quote($user->id) . ') OR (f.sender_id = ' . $dbo->quote($user->id) . ' AND f.receiver_id = ' . $dbo->quote($userId) . '))') ->where('f.type = ' . $dbo->quote($type));
$result = $dbo->setQuery($query) ->loadObject();
return $result;
}
public function usersInRelationship($receiverId, $senderId) {
$dbo = $this->getDbo();
$users = array($dbo->quote($receiverId), $dbo->quote($senderId));
$query = $dbo->getQuery(true) ->select('f.id, f.sender_id, f.receiver_id') ->from('#__lovefactory_friends f') ->where('(f.sender_id IN ('.implode(',', $users).') OR f.receiver_id IN ('.implode(',', $users).'))') ->where('f.type = ' . $dbo->quote(2)) ->where('f.pending = ' . $dbo->quote(0));
$result = $dbo->setQuery($query) ->loadObject();
if ($result) {
if ($receiverId == $result->sender_id || $receiverId == $result->receiver_id) {
$this->setError(FactoryText::_('friend_task_accept_error_you_already_are_in_a_relationship'));
}
else {
$this->setError(FactoryText::_('friend_task_accept_error_requesting_user_already_is_in_a_relationship'));
}
return true;
}
return false;
}
Is there any special way how the file must be written? Or did anyone else had the same problem?
The problem was caused by the line endings.
NetBeans changed the line endings and then the server was not able with function require_once load the content correctly.
Solution was download a plugin to NetBeans that allows to change line endings.
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);
?>