this might be a bit tricky. First here is my function:
public function transfer_smf_userinfo($username)
{
$sys_columns = implode(', ', $this->_config['bbauth']['columns']['sys']);
$smf_columns = implode(', ', $this->_config['bbauth']['columns']['smf']);
$question_marks;
for($i = 0; $i > sizeof($this->_config['bbauth']['columns']['sys']); $i++)
{
if(sizeof($this->_config['bbauth']['columns']['sys']) == $i - 1)
{
$question_marks .'?';
}
else {
$question_marks .'?, ';
}
}
$user = $this->smf_db->query('SELECT '. $smf_columns .' FROM `smf_members` WHERE member_name = ? LIMIT 1', array($username));
if($user->num_rows > 0)
{
$user = $user->row_array();
$user['register_date'] = date('Y-m-d H:i:s', $user['register_date']);
$user['last_login'] = date('Y-m-d H:i:s', $user['last_login']);
$transfer_user = $this->sys_db->query('INSERT INTO `members` ('. $sys_columns .') VALUES ('. $question_marks .')', array());
if($transfer_user)
{
return true;
}
else {
return false;
}
}
else {
return false;
}
}
$sys_columns outputs:
id, username, password, email, url, avatar, b_date, r_date, l_date
$smf_columns outputs:
id_member, member_name, passwd, email_address, website_url, avatar, birthdate, date_registered, last_login
I need the array at the end of the line on the $transfer_user query to have a array like so.
array($user['column'], $user['another']);
But I need to do it dynamically with each row from $smf_columns.
If I understand the issue correctly. Try:
$data=array();
foreach($this->_config['bbauth']['columns']['smf'] as $column)
$data[]=$user[$column];
$transfer_user = $this->sys_db->query(
'INSERT INTO `members` ('. $sys_columns .') VALUES ('. $question_marks .')',
$data);
Related
function insert_data($data, $table, $action )
{
include "connect.php";
$columnnvalues = json_decode(json_encode($data), true);
$columns = array ();
$values = array();
foreach($columnnvalues as $key=>$col)
{
foreach($col as $keyval=>$val)
{
array_push($columns, $col);
array_push($values, $val);
}
}
$sql = "INSERT INTO " .$table. " (" .implode(", ", $columns).") VALUES (".implode(", ", $values). ")";
echo $sql;
$stmt = mysqli_prepare($con,$sql);
if($stmt)
{
mysqli_stmt_execute($stmt);
$result["success"] = true;
}
else
{
$result["success"] = false;
$result["error"] = 1;
}
echo json_encode($result);
}
sample datas
$datas = Array ("name"=>"sample", "permanentaddress"=>"add", "contact"=>"aaaa", "status"=>"Active");
insert_data($datas, "customers", "add" )
code:
$new_deb = 5;
//prepare query();
$q = 'START TRANSACTION;';
for($l = 0; $l < $cond; $l++){
if($uploaded == 0 || $uploaded == "0"){
$q .= ' INSERT INTO vocher (`vo_type_id`, `account_id`, `value`, `desc`, `user_id`, `status_id`, `date`, `debtor_id`)';
$q .= ' VALUES ("'.$vouchertype.'", "'.$voucheracc[$l].'","'.$vdebvalue[$l].'", "'.$vdebdesc[$l].'","'.$_POST['usrSes'].'", "'.$status.'","'.$vocherdate[$l].'", "'.$new_deb.'");';
}else{
$q .= ' INSERT INTO vocher (`vo_type_id`, `account_id`, `value`, `desc`, `user_id`, `status_id`, `date`, `debtor_id`, `link`)';
$q .= ' VALUES ("'.$vouchertype.'", "'.$voucheracc[$l].'","'.$vdebvalue[$l].'", "'.$vdebdesc[$l].'","'.$_POST['usrSes'].'", "'.$status.'","'.$vocherdate[$l].'", "'.$new_deb.'", "'.$newAttach.'");';
}
$q .= ' SET #lastId = (SELECT `id` FROM vocher ORDER BY `id` DESC LIMIT 1);';
if($voCc[$l] != 'e'){
for($h = 0; $h < count($voCc[$l]); $h++){
if($voCc[$l][$h] != 'e'){
$q .= ' INSERT INTO voucher_cc (`voucher`, `cc`) VALUES (#lastId, "'.$voCc[$l][$h].'");';
}
}
}
if(in_array($voucheracc[$l], $inResetAccs)){
$q .= ' INSERT INTO resets ( `type`, `acc`, `user`, `value`, `desc`, `debtor_id`, `date`, `status`)';
$q .= ' VALUES ("IN", "'.$voucheracc[$l].'", "'.$_POST['usrSes'].'", "'.$vdebvalue[$l].'", "'.$vdebdesc[$l].'", "'.$new_deb.'", "'.$vocherdate[$l].'", "1");';
}
}
for($z = 0; $z < $chqradiolength; $z++){
if ($chqradio[$z] == "0") {
$q .= ' INSERT INTO creditor (`acc_id`, `value`, `bank_id`, `debtor_id`, `cheque_no`, `issue_date`, `available_date`, `vo_type_id`, `desc`, `date`, `user`)';
$q .= ' VALUES ("'.$chequeAcc[$z].'", "'.$vvalue[$z].'", "'.$banks[$z].'", "'.$new_deb.'", "'.$vsn[$z].'", "'.$issuesdates[$z].'", "'.$availabledate[$z].'", "'.$vouchertype.'", "'.$vdesc[$z].'", "'.$credates[$z].'", "'.$_POST['usrSes'].'");';
$q .= ' SET #creLastId = (SELECT `id` FROM creditor ORDER BY `id` DESC LIMIT 1);';
for($x = 0; $x < count($chequeCc[$z]); $x++){
$q .= ' INSERT INTO creditor_cc (`creditor`, `cc`) VALUES (#creLastId, "'.$chequeCc[$z][$x].'");';
}
}else{
$q .= ' INSERT INTO creditor (`acc_id`, `value`, `debtor_id`, `date`, `desc`, `vo_type_id`, `user`)';
$q .= ' VALUES ("'.$creaccs[$z].'", "'.$vvalue[$z].'", "'.$new_deb.'" , "'.$credates[$z].'" , "'.$vdesc[$z].'" , "'.$vouchertype.'", "'.$_POST['usrSes'].'");';
$q .= ' SET #creLastId = (SELECT `id` FROM creditor ORDER BY `id` DESC LIMIT 1);';
if($creCc[$z] != 'e'){
for($x = 0; $x < count($creCc[$z]); $x++){
if($creCc[$z][$x] != 'e'){
$q .= ' INSERT INTO creditor_cc (`creditor`, `cc`) VALUES (#creLastId, "'.$creCc[$z][$x].'");';
}
}
}
if(in_array($creaccs[$z], $outResetAccs)){
$q .= ' INSERT INTO resets (`type`, `acc`, `user`, `value`, `desc`, `debtor_id`, `date`, `status`)';
$q .= ' VALUES ("OUT", "'.$creaccs[$z].'" , "'.$_POST['usrSes'].'" , "'.$vvalue[$z].'", "'.$vdesc[$z].'" , "'.$new_deb.'", "'.$credates[$z].'", "1");';
}
}
}
$q .= ' COMMIT;';
$vocher_obj->query($q);
$check = $vocher_obj->execute();
if($check){
$res = 1;
}else{
$res = 23;
}
echo $res;
This code is to generate some queries.
Those queries always return "true" even if I change the table name to a "non existing" table in the database, while it should return "false"!
Could you please help me with this?
Maybe this is caused by this bug: https://bugs.php.net/bug.php?id=61613
It says, if the FIRST statement is valid, pdo will not return an error. And START TRANSACTION; is always valid.
The bug is reported to be unfixed upto verison 5.6.7 of PHP.
Not sure if this bug affects the return statement as well, as it is about missing exception throwing. But should be easy to test: Add a invalid statement before anything else and see if the return value is false.
Also for transactions with pdo you should look at
$pdo->beginTransaction();
$pdo->commit();
$pdo->rollback();
To avoid the bug mentioned above, stuff your queries into an array, and run them like this (simplified):
function runQueries($pdo, $queries){
try{
$pdo->beginTransaction();
foreach($queries as $q){
$pdo->exec($q);
}
$pdo->commit();
return true;
}catch (PDOException $e){
$pdo->rollback();
return false;
}
}
ofc. you need to configure PDO to throw execptions, using
$pdo = new PDO('mysql:host=localhost;dbname=someDB', 'username', 'password', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
I am passing a number of values to a function and then want to create a SQL query to search for these values in a database.
The input for this is drop down boxes which means that the input could be ALL or * which I want to create as a wildcard.
The problem is that you cannot do:
$result = mysql_query("SELECT * FROM table WHERE something1='$something1' AND something2='*'") or die(mysql_error());
I have made a start but cannot figure out the logic loop to make it work. This is what I have so far:
public function search($something1, $something2, $something3, $something4, $something5) {
//create query
$query = "SELECT * FROM users";
if ($something1== null and $something2== null and $something3== null and $something4== null and $something5== null) {
//search all users
break
} else {
//append where
$query = $query . " WHERE ";
if ($something1!= null) {
$query = $query . "something1='$something1'"
}
if ($something2!= null) {
$query = $query . "something2='$something2'"
}
if ($something3!= null) {
$query = $query . "something3='$something3'"
}
if ($something4!= null) {
$query = $query . "something4='$something4'"
}
if ($something5!= null) {
$query = $query . "something5='$something5'"
}
$uuid = uniqid('', true);
$result = mysql_query($query) or die(mysql_error());
}
The problem with this is that it only works in sequence. If someone enters for example something3 first then it wont add the AND in the correct place.
Any help greatly appreciated.
I would do something like this
criteria = null
if ($something1!= null) {
if($criteria != null)
{
$criteria = $criteria . " AND something1='$something1'"
}
else
{
$criteria = $criteria . " something1='$something1'"
}
}
... other criteria
$query = $query . $criteria
try with array.
function search($somethings){
$query = "SELECT * FROM users";
$filters = '';
if(is_array($somethings)){
$i = 0;
foreach($somethings as $key => $value){
$filters .= ($i > 0) ? " AND $key = '$value' " : " $key = '$value'";
$i++;
}
}
$uuid = uniqid('', true);
$query .= $filters;
$result = mysql_query($query) or die(mysql_error());
}
// demo
$som = array(
"something1" => "value1",
"something2" => "value2"
);
search( $som );
Here's an example of dynamically building a WHERE clause. I'm also showing using PDO and query parameters. You should stop using the deprecated mysql API and start using PDO.
public function search($something1, $something2, $something3, $something4, $something5)
{
$terms = array();
$values = array();
if (isset($something1)) {
$terms[] = "something1 = ?";
$values[] = $something1;
}
if (isset($something2)) {
$terms[] = "something2 = ?";
$values[] = $something2;
}
if (isset($something3)) {
$terms[] = "something3 = ?";
$values[] = $something3;
}
if (isset($something4)) {
$terms[] = "something4 = ?";
$values[] = $something4;
}
if (isset($something5)) {
$terms[] = "something5 = ?";
$values[] = $something5;
}
$query = "SELECT * FROM users ";
if ($terms) {
$query .= " WHERE " . join(" AND ", $terms);
}
if (defined('DEBUG') && DEBUG==1) {
print $query . "\n";
print_r($values);
exit();
}
$stmt = $pdo->prepare($query);
if ($stmt === false) { die(print_r($pdo->errorInfo(), true)); }
$status = $stmt->execute($values);
if ($status === false) { die(print_r($stmt->errorInfo(), true)); }
}
I've tested the above and it works. If I pass any non-null value for any of the five function arguments, it creates a WHERE clause for only the terms that are non-null.
Test with:
define('DEBUG', 1);
search('one', 'two', null, null, 'five');
Output of this test is:
SELECT * FROM users WHERE something1 = ? AND something2 = ? AND something5 = ?
Array
(
[0] => one
[1] => two
[2] => five
)
If you need this to be more dynamic, pass an array to the function instead of individual arguments.
I have a very complicated funciton in one of my CI models so I try to optimise it and make it more robust.I'm not sure where exactly the problem is so I'll paste both the original(working) variant and what I have done to make it better. I think in the most part it should work but obv. I've made a mistake somewhere along the way.
Here is the original function:
public function get($data)
{
if (isset($data))
{
if (isset($data['sort']))
{
$sort = json_decode($data['sort'], true);
$this->db->order_by($sort[0]['property'], $sort[0]['direction']);
}
if (isset($data['query']) && $data['query'] != '')
{
$fields = json_decode($data['fields'], true);
$where = $fields[0] . " LIKE '%" . $data['query'] . "%'";
unset($fields[0]);
foreach ($fields as $field)
{
$where .= ' OR ' . $field . ' LIKE ' . "'%" . $data['query'] . "%'";
}
$this->db->select('id, email, firstname, lastname, usertype, ts_created, ts_last_login, position');
$this->db->from('users');
$this->db->where($where);
$this->db->limit($data['limit'], $data['start']);
$query = $this->db->get();
$result = $query->result_array();
}
else
{
$this->db->select('id, email, firstname, lastname, usertype, ts_created, ts_last_login, position');
$this->db->from('users');
$this->db->limit($data['limit'], $data['start']);
$query = $this->db->get();
$result = $query->result_array();
}
if ($result != null)
{
return $result;
}
else
{
return null;
}
}
else
{
$query = $this->db->select('id, email, firstname, lastname, usertype, ts_created, ts_last_login, position');
$query = $this->db->get('users');
$result = $query->result_array();
return $result;
}
}
And here is what I've done:
public function get($data)
{
if (isset($data))
{
if (isset($data['sort']))
{
$sort = json_decode($data['sort'], true);
$orderCoulmn = $sort[0]['property'];
$orderDir = $sort[0]['direction'];
}
$limit = $data['limit'];
$start = $data['start'];
}
$this->db->select('id, email, firstname, lastname, usertype, ts_created, ts_last_login, position');
/* if (!empty($where))
{
$this->db->where($where);
}*/
if (isset($data['query']) && $data['query'] != '' )
{
$fields = json_decode($data['fields'], true);
//$this->db->like($fields[0], $data['query']);
//unset($fields[0]);
foreach ($fields as $filed)
{
$this->db->or_like($field, $data['query']);
}
}
if (!empty($limit) && !empty($start))
{
$this->db->limit($limit, $start);
}
if (!empty($orderColumn) && !empty($orderDir))
{
$this->db->order_by($orderColumn, $orderDir);
}
$query = $this->db->get('users');
$result = $query->result_array();
return $result;
}
Any ideas where could be the problem in my code (the second one)?
Thanks
Leron
I don't directly see what's wrong with your example, but this is how I would simplify things:
public function get($data)
{
$this->db->select('id, email, firstname, lastname, usertype, ts_created, ts_last_login, position'); // same for every situation
if (is_array($data)) // a little stricter than testing if it's set, could be a string.
{
$this->db->limit($data['limit'], $data['start']); // do anyhow if $data is an array
if ($data['sort']) // if this evaluates to true, execute
{
$sort = json_decode($data['sort'], true);
$this->db->order_by($sort[0]['property'], $sort[0]['direction']);
}
if ($data['query'])
{
$fields = json_decode($data['fields'], true);
$where = "";
$seperator = "";
foreach($fields as $field)
{
$where .= "{$seperator}$field LIKE '%{$data['query']}%'";
$seperator = ' OR '; // using this "seperator" approach, allows you to easily concat strings.
}
$this->db->where($where);
}
}
// finally, get a result, with possible other db actions, depending on $data
$query = $this->db->get('users');
$result = $query->result_array();
return $result;
}
Remember: KISS and DRY are your friends ;)
I have the following code:
$sql = "SELECT name, address, city FROM tableA, tableB WHERE tableA.id = tableB.id";
if (isset($price) ) {
$sql = $sql . ' AND price = :price ';
}
if (isset($sqft) ) {
$sql = $sql . ' AND sqft >= :sqft ';
}
if (isset($bedrooms) ) {
$sql = $sql . ' AND bedrooms >= :bedrooms ';
}
$stmt = $dbh->prepare($sql);
if (isset($price) ) {
$stmt->bindParam(':price', $price);
}
if (isset($sqft) ) {
$stmt->bindParam(':price', $price);
}
if (isset($bedrooms) ) {
$stmt->bindParam(':bedrooms', $bedrooms);
}
$stmt->execute();
$result_set = $stmt->fetchAll(PDO::FETCH_ASSOC);
What I notice is the redundant multiple IF statements I have.
Question: is there any way to clean up my code so that I don't have these multiple IF statements for prepared statements?
This is very similar to a question a user asked me recently the forum for my book SQL Antipatterns. I gave him an answer similar to this:
$sql = "SELECT name, address, city FROM tableA JOIN tableB ON tableA.id = tableB.id";
$params = array();
$where = array();
if (isset($price) ) {
$where[] = '(price = :price)';
$params[':price'] = $price;
}
if (isset($sqft) ) {
$where[] = '(sqft >= :sqft)';
$params[':sqft'] = $sqft;
}
if (isset($bedrooms) ) {
$where[] = '(bedrooms >= :bedrooms)';
$params[':bedrooms'] = $bedrooms;
}
if ($where) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
$stmt = $dbh->prepare($sql);
$stmt->execute($params);
$result_set = $stmt->fetchAll(PDO::FETCH_ASSOC);
Instead of if else just use PHP ternary operator
if (isset($_POST['statusID']))
{
$statusID = $_POST['statusID'];
}
else
{
$statusID = 1;
}
instead of that you can do:
$statusID = (isset($_POST['statusID'])) ? $_POST['statusID'] : 1;
The format of the ternary operator is: $variable = condition ? if true : if false
The beauty of it is that you will shorten your if/else statements down to one line and if compiler ever gives you errors, you can always go back to that line instead of 3 lines.