How use an array/implode in the SELECT query PDO - php

i have a function that returns user data from the database. But I want to return only the selected row, for instance username, so i created an array for that, giving the option to echo $userdata['anything']. see the code:
$session_user_id = $_SESSION['user_id'];
$user_data = user_data($session_user_id, 'user_id', 'username', 'password', 'first_name', 'last_name'); }
and
function user_data($user_id){
$pdo = new PDO("mysql:host=localhost;dbname=MYDATABASE;", "MYUSERNAME", "MYPASSWORD");
$data = array();
$user_id = (int)$user_id;
$func_num_args = func_num_args();
$func_get_args = func_get_args();
if ($func_num_args > 1) {
unset($func_get_args[0]);
$fields = '`' . implode(', ', $func_get_args) . '`';
echo $fields;
$stmt = $pdo->prepare("SELECT :fields FROM `users` WHERE `user_id` = :user_id");
$stmt->execute(array(':user_id' => $user_id, ':fields' => $fields));
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);
}
}
The problem is that this doesn't work. It returns
Array ( [0] => Array ( [`user_id, username, password, first_name, last_name`] => `user_id, username, password, first_name, last_name` ) )
However, replacing :fields with for instance 'username' does work. Is it possible to use this implode?

Change:
$stmt = $pdo->prepare("SELECT :fields FROM `users` WHERE `user_id` = :user_id");
to:
$stmt = $pdo->prepare("SELECT $fields FROM `users` WHERE `user_id` = :user_id");
and remove $fields from the execute parameter array.
Parameterized placeholders are only for values.
UPDATE
Also this line is wrong:
$fields = '`' . implode(', ', $func_get_args) . '`';
This will output a ` outside the the field list rather than each column name.
Try removing them like this:
$fields = implode(', ', $func_get_args);

Related

Update Row Fields if POST['submitted_field'] Is Not Null MariaDB , MySQL

Hi I'm trying to update user information on valid submit
in my query it's possible to update multiple columns only if it's relevant $_POST[ ] is not null
how i can do that ? used tool php , MariaDB or mysql I. I tried something like this but it returns syntax error corresponding to MariaDB
$query = " UPDATE `users`
SET name = COALESCE($name, name),
title = COALESCE($title, title),
email = COALESCE($email, email),
gender = COALESCE($gender, gender)
WHERE `id` = '" . $_SESSION['id'] . "' LIMIT 1";
You can have a helper for doing that
function getUserUpdateQuery(array $data, $userId)
{
$condition = 'WHERE id = '.$userId;
$query = 'UPDATE `users` SET ';
$updates = [];
foreach ($data as $columnName => $columnValue) {
if( !is_null($columnValue) )
{
$updates[] = sprintf('`%s` = \'%s\'', $columnName, $columnValue);
}
}
$query .= implode(' AND ', $updates).' ';
$query .= $condition;
return $query;
}
$query = getUserUpdateQuery(['title' => $title, 'email' => $email], $_SESSION['id']);
// updating codes here
Note: in production environment it is better practice to bind data. PDO is a good tool for doing that.

Indexing array in php pdo insert while loop

I'm trying to insert a row into a table for each fetch from another table using a while loop. The code I currently have inserts the first users data into the database.
If the insert query is outside of the loop it will enter the last users data. It must be an issue iterating through the array. Is there a way I can index the array values for each pass of the loop?
$query = "SELECT * FROM users_table" ;
$statement = $db->prepare($query);
$rows = $statement->fetchAll();
$statement->execute();
while($rows = $statement->fetch()){
$salted = $sso_key . $companyId;
$hash = hash('sha1',$salted,true);
$saltedHash = substr($hash,0,16);
$iv = substr(md5(microtime()),rand(0,16),16); //Generate random 16 bit string
$user_data = array(
"user_id" => $rows['id'],
"first_name" => $rows['first_name'],
"last_name" => $rows['last_name'],
"email" => $rows['email'],
"position" => $rows['type']);
$data = json_encode($user_data);
$data = $iv . $data;
$pad = 16 - (strlen($data) % 16);
$data = $data . str_repeat(chr($pad), $pad);
$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128,'','cbc','');
mcrypt_generic_init($cipher, $saltedHash, $iv);
$encryptedData = mcrypt_generic($cipher,$data);
mcrypt_generic_deinit($cipher);
$encryptedData = base64_encode($encryptedData);
$token = array(
"token" => $encryptedData
);
$token_data = json_encode($token);
echo "
<br>Here is the token for ".$user_data['first_name'].", ".$user_data['last_name']."
".$user_data['email'] ." :
" . $token['token'];
$query = "INSERT INTO another_table
(token ,first_name,last_name,email,position)
VALUES (:token, :first_name,
:last_name, :email, :position)";
$statement = $db->prepare($query);
$statement->bindValue(':token', $token['token']);
$statement->bindValue(':first_name', $user_data['first_name']);
$statement->bindValue(':last_name', $user_data['last_name']);
$statement->bindValue(':email', $user_data['email']);
$statement->bindValue(':position', $user_data['position']);
$statement->execute();
}
?>
Reducing that code to the basics, you have this:
$query = "SELECT * FROM users_table" ;
$statement = $db->prepare($query);
$rows = $statement->fetchAll();
$statement->execute();
while($rows = $statement->fetch()){
// .. stuff ..
$query = "INSERT INTO another_table
(token ,first_name,last_name,email,position)
VALUES (:token, :first_name,
:last_name, :email, :position)";
$statement = $db->prepare($query);
$statement->bindValue(':token', $token['token']);
$statement->bindValue(':first_name', $user_data['first_name']);
$statement->bindValue(':last_name', $user_data['last_name']);
$statement->bindValue(':email', $user_data['email']);
$statement->bindValue(':position', $user_data['position']);
$statement->execute();
}
See the problem yet? Ok, here is a hint to fix it:
$query = "SELECT * FROM users_table" ;
$statement = $db->prepare($query);
$statement->execute();
$query = ".. prepared query here .."; // your second query used in the loop
$SECOND_statement = $db->prepare($query); // set it up
while($row = $statement->fetch()){
// .. bindValue lines here ..
$SECOND_statement->execute();
}
Inside your while loop, you were overwriting the variable $statement with the insert sql. This effectively ended your while loop prematurely. Can also cause some serious unwanted and unexpected issues if that second sql was another SELECT.

PHP submit to insert and update data

I need my form to post either INSERT or UPDATE data, depending on whether the column already exists. The INSERT query works fine, but the UPDATE doesn't. I guess this would be because the initial sql query ($query) is failing, more than likely because it is not finding the $Unique_Ref POST data. If this is the case, how do I extract this single value from the $invoice_data array?
This is the form page code:
if (isset($_GET['success']) && empty($_GET['success'])) {echo 'Record saved'; } else {if (empty($_POST) === false && empty($errors) === true) {$invoice_data = array(
'Unique_Ref' => mysqli_real_escape_string($conn, $_POST['Unique_Ref']),
'Supplier_Name' => mysqli_real_escape_string($conn, $_POST['Supplier_Name']),
'Supplier_Invoice_Ref' => mysqli_real_escape_string($conn, $_POST['Supplier_Invoice_Ref']),
'Office' => mysqli_real_escape_string($conn, $_POST['Office']),
'Loss_Surplus_Amount' => mysqli_real_escape_string($conn, $_POST['Loss_Surplus_Amount']),
'Loss_Surplus_Currency' => mysqli_real_escape_string($conn, $_POST['Loss_Surplus_Currency']),
'Outcome' => mysqli_real_escape_string($conn, $_POST['Outcome']));
save_invoice($invoice_data);header('Location: invoices.php?success'); exit();
} else if (empty($errors) === false) {echo output_errors($errors);} ?> *html form....*
This is the save_invoice() function:
function save_invoice($invoice_data) {
global $conn;
array_walk($invoice_data, 'array_sanitize');
$fields = '`' . implode('`, `', array_keys($invoice_data)) . '`';
$data = '\'' . implode('\', \'', $invoice_data) . '\'';
$query = mysqli_query($conn, "SELECT * FROM `invoicelog` WHERE `Unique_Ref` = '$Unique_Ref'");
$result = mysqli_num_rows($query);
if($result > 0) {
mysqli_query($conn, "UPDATE `invoicelog` SET $fields = $data WHERE `Unique_Ref` = '$Unique_Ref'");
} else {
mysqli_query($conn, "INSERT INTO `invoicelog` ($fields) VALUES ($data)");
}
Any suggestions would be very welcome. As I mentioned, the final INSERT query works fine, it's the UPDATE query which isn't functioning.
Your have to pair your
$fields = '`' . implode('`, `', array_keys($invoice_data)) . '`';
$data = '\'' . implode('\', \'', $invoice_data) . '\'';
Edit
i've edited you code like this:
$fields = array_keys($invoice_data)[$i];
$data = $invoice_data;
to achieve whats below, and it works for me.. hmm..
End Edit
something like :
'fields[0] = $data[0], ...' //and so on, place it in a loop. or whatever you prefer.. :)
because when updating it's (field1 = value1, field2 = value)
Edit2
Actual code of testing:
End Edit
maybe something like this will do?
$set_arr = array();
for ($i = 0; $i < count($data); $i++)
{
$set_arr[] = "`".array_keys($invoice_data)[$i]/*$fields*/."` = '".$data[$i]."' ";
}
$setString = implode(',', $set_arr);
/*
Result ]> `Unique_Ref` = '1' ,`Supplier_Name` = '2' ,`Supplier_Invoice_Ref` = '3' ,`Office` = '4' ,`Loss_Surplus_Amount` = '5' ,`Loss_Surplus_Currency` = '6' ,`Outcome` = '7'
]> from my test
*/
then your update statement will be something like this:
"UPDATE `invoicelog` SET ($setString) `Unique_Ref` = '$Unique_Ref'
Hope i've helped you.. i'm outta here, Happy Coding Cheers!
You can't set multiple values to multiple fields within single expression like SET $fields = $data. You should set each value for each field separately: SET field1='value1', field2='value2', ...
//mysqli_query($conn, "UPDATE invoicelog SET $fields = $data WHERE Unique_Ref = '$Unique_Ref'");
update below code with above line.
$str = '';
foreach($invoice_data as $field=>$val ){
$str = $str.",".$field."=".$val;
}
$str = substr($str,1);
mysqli_query($conn, "UPDATE `invoicelog` SET $str WHERE Unique_Ref = '$Unique_Ref'");
make sure insert quote (') for string value :
mysqli_query($conn, "UPDATE `invoicelog` SET $fields = '$data' WHERE `Unique_Ref` = '$Unique_Ref'");

Passing variable to static function

I have some PHP that pulls all staff records in the DB.
I now want to add a clause, so it can SELECT * WHERE companyId = x.
Im using GET to retrieve the companyId to be used.
My question is, how can I pass $companyClause to the static function?
function viewStaffInCompany(){
$results = array();
$companyClause = $_GET["companyClause"];
echo $companyClause . "<br><hr>";
$data = Staff::getCompanyStaffList();
$results['staff'] = $data['results'];
$results['totalRows'] = $data['totalRows'];
require( "templates/viewStaff.php" );
};
and
getCompanyStaffList();
public static function getCompanyStaffList( $numRows=1000000, $order="id ASC", $companyClause) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT SQL_CALC_FOUND_ROWS * FROM Staff WHERE $companyClause ORDER BY " . $order . " LIMIT :numRows";
$st = $conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();
$list = array();
while ( $row = $st->fetch() ) {
$users = new Staff( $row );
$list[] = $users;
}
// Now get the total number of staff that matched the criteria
$sql = "SELECT FOUND_ROWS() AS totalRows";
$totalRows = $conn->query( $sql )->fetch();
$conn = null;
return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
}
Just as a parameter.
Staff::getCompanyStaffList(1000000, "id ASC", $companyClause);
But I would refactore this parameter list, because $companyClause is required, so, you will need to pass the first 2 params always, what has default values, if not given.
So it should be:
public static function getCompanyStaffList($companyClause, $numRows=1000000, $order="id ASC") {

PHP and PDO prepared statments - Column not found

I have a problem with a "unknown" column.
This is the error I get back in firebug.
ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'admin' in 'where clause'UPDATE users SET session_key = 1234567890 WHERE username = 'admin'
this is the parameters and call statement
$table = 'users';
$fields_vals = array( 'session_key' => $session_key );
$where = array('username' => $username);
$dbResult = $this->DB->sql_update($fields_vals, $table, $where);
/*
* UPDATE
* $data -> assoc array containing (field => value) to be UPDATED.
* $where -> Where clause (only a single argument)
* $table -> to be updated
*/
public function sql_update($fieldsVals, $table, $where)
{
try {
//Values to be updated in in a assoc array
//Extract values and fields and concatenate with '=' ( field = value )
$upd_string = '';
foreach($fieldsVals as $name => $value){
$upd_string .= $name .' = :'. $name .' ,';
}
//Trim last comma that was appended
$upd_string = rtrim($upd_string, ',');
// Formulate the where clause
$where_str = '';
foreach($where as $wName => $wValue){
$where_str .= "$wName = $wValue";
}
//Set Query
//$query = "UPDATE {$table} SET {$upd_string} WHERE $where_str";
// THIS IS WHERE I EXPLICITLY RAN THE QUERY, BUT GOT EXACTLY THE SAME ERROR.
$query = "UPDATE users SET session_key = 1234567890 WHERE username = 'admin'";
$stmt = $this->conn->prepare($query);
//Exec
foreach($fieldsVals as $k => &$v){
$stmt->bindParam(":{$k}", $v);
}
$stmt->execute();
return true;
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
return false;
}
}
Here is proof that the column does exist.
PLEASE NOTE -> where username = 'admin'
Try passing your WHERE attribute in as a prepared variable:
$query = "UPDATE users SET session_key = 1234567890 WHERE username = :username";
$fieldsVals[":username"] = "admin";
$where_str .= "$wName = '$wValue'";
Otherwise your query comes as "WHERE username = admin"
What you should do to use prepared statements for the whole query, so you should change your function from the current one into:
function sql_update($fieldsVals, $table, $where)
{
//Values to be updated in in a assoc array
//Extract values and fields and concatenate with '=' ( field = value )
$upd_string = '';
foreach ($fieldsVals as $name => $value) {
$upd_string .= $name . ' = :set_' . $name . ' ,';
}
//Trim last comma that was appended
$upd_string = rtrim($upd_string, ',');
// Formulate the where clause
$where_str = '';
foreach ($where as $wName => $wValue) {
$where_str .= $wName . ' = :wh_' . $wName . ' ,';
}
//Trim last comma that was appended
$where_str = rtrim($where_str, ',');
//Set Query
$query = "UPDATE {$table} SET {$upd_string} WHERE $where_str";
$stmt = $this->conn->prepare($query);
//Exec
foreach ($fieldsVals as $k => &$v) {
$stmt->bindParam(":set_{$k}", $v);
}
foreach ($where as $k => &$v) {
$stmt->bindParam(":wh_{$k}", $v);
}
$stmt->execute();
return true;
}
The correct usage would be:
$stmt = $this->conn->prepare('UPDATE users SET session_key = :session WHERE username = :username');
$stmt->bindParam(':session', session_id(), PDO::PARAM_STR);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
Then execute.
I think your variable $fieldsVals is wrong due to the foreach's you do. Maybe you switching key und val by accident, resulting in WHERE admin=username.
Update:
#MarcinNabiaƂek is right of course you are missing quotes.
But it seems like the error is coming from a different part of the script.
It seems you don't use ' in your query in PHP. Either you don't use it or use other symbol that look similar.
If I run in phpmyAdmin query:
UPDATE users SET session_key = 1234567890 WHERE username = admin
I also get error message:
#1054 - Unknown column 'admin' in 'where clause'
but when I have
UPDATE users SET session_key = 1234567890 WHERE username = 'admin'
it works fine
In your code you should definitelly change:
$where_str .= "$wName = $wValue";
into
$where_str .= "$wName = '$wValue'";
session_key is a varchar
You have to use the query like the below,
$query = "UPDATE users SET session_key = '1234567890' WHERE username = 'admin'";
column admin doesn't exist! column administrator exists though.
I don't see any admin column in your mysql table in the screenshot that you provided.
You can simply change the name of the administrator column in your mysql table to admin and everything will work.

Categories