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.
Related
This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 5 years ago.
so I was following a Udemy course and then the instructor made this function
public function update($table, $user_id, $fields = array()){
$columns = '';
$i = 1;
foreach($fields as $name => $value){
$columns .= "'{$name}' = :{$name}";
if($i < count($fields)){
$columns .= ', ';
}
$i++;
}
$sql = "UPDATE {$table} SET {$columns} WHERE 'user_id' = {$user_id}";
if($stmt = $this->pdo->prepare($sql)){
foreach($fields as $key => $value){
$stmt->bindValue(':'.$key, $value);
}
$stmt->execute();
}
}
And I wrote it literally so many times after him and it just never seemed to work, would someone explain for me what's wrong with the code?
here
$sql = "UPDATE {$table} SET {$columns} WHERE 'user_id' = {$user_id}";
the ' around the table name should be backticks, not single quotes:
$sql = "UPDATE {$table} SET {$columns} WHERE `user_id` = {$user_id}";
same here:
$columns .= "`{$name}` = :{$name}";
You should replace single quotes with backticks:
$columns .= "`{$name}` = :{$name}";
and
$sql = "UPDATE {$table} SET {$columns} WHERE `user_id` = {$user_id}";
Just a suggestion: You could use an array to build the columns clause and you could directly execute without any bindValue, by just passing the $fields array:
function update($table, $user_id, $fields = array()) {
$columns = [];
foreach ($fields as $name => $value) {
$columns[] = "`{$name}` = :{$name}";
}
$sql = sprintf('UPDATE %s SET %s WHERE `user_id` = %s'
, $table
, implode(', ', $columns)
, $user_id
);
if ($stmt = $this->pdo->prepare($sql)) {
$stmt->execute($fields);
}
}
I have a simple method that is not working as it should - would like to use prepared statements but somehow it is not executed; instead the raw query works just fine.
What could be the problem? Should I pass some extra args to pdo methods?
$_POST['sequence'] = [
0 => 2,
1 => 1
];
if (!empty($_POST['sequence'])) {
$query = '
UPDATE '.$this->db->backtick($this->controller->table).'
SET `sequence` = CASE `id`'
;
foreach ($_POST['sequence'] as $sequence => $id) {
$values[':id'.$id] = $id;
$values[':sequence'.$sequence] = $sequence;
$query .= ' WHEN :id'.$id.' THEN :sequence'.$sequence;
}
$values[':ids'] = implode(',', array_values($_POST['sequence']));
$query .= ' END WHERE `id` IN (:ids)';
$statement = $this->db->handle->prepare($query);
$statement->execute($values); //doesn't work
//$query2 = str_replace(array_keys($values), array_values($values), $query);
//$this->db->handle->query($query2); works
}
Don't bind the param inside IN
$query .= ' END WHERE `id` IN ('.implode(',', array_values($_POST['sequence'])).')';
Hi All,
I am trying to make a search form work with multiple fields. The user is free to fill whatever field he wishes and leave the others blank. The search box looks like this.
Search Box Image with result table at bottom:
I know how to make it work without PDO with old mysql code.
PHP CODE FOR SEARCH IS :
<?php
if(isset($_POST['submit'])){
// define the list of fields
$fields = array('first_name', 'last_name', 'email', 'job', 'country', 'city');
$conditions = array();
// loop through the defined fields
foreach($fields as $field){
// if the field is set and not empty
if(isset($_POST[$field]) && $_POST[$field] != '') {
// create a new condition while escaping the value inputed by the user (SQL Injection)
$conditions[] = "`$field` LIKE '%" . mysql_real_escape_string($_POST[$field]) . "%'";
}
}
$con = mysql_connect("localhost","root","");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("php_test", $con) or die("ERROR");
// builds the query
$query = "SELECT * FROM people ";
// if there are conditions defined
if(count($conditions) > 0) {
// append the conditions
$query .= "WHERE " . implode (' OR ', $conditions); // you can change to 'OR', but I suggest to apply the filters cumulative
}
// echo $query;
$result = mysql_query($query);
}
?>
(Note: I have not included any validation but I will do it)
It's working just fine but I wanted to do the same using PDO.
I know that if I do something like below code it will work in PDO :-
$q = $_POST['q'];
$search = $db->prepare("SELECT `id`, `name` FROM `users` WHERE `name` LIKE ?");
$search->execute(array("%$q%"));
foreach($search as $s) {
echo $s['name'];
}
But I am having a hard time figuring out how to do it multiple fields and use prepared statement. Even a hint in the right direction will be very very helpful.
Thank You All in Advance.
You can do it like you did before:
$fields = array('first_name', 'last_name', 'email', 'job', 'country', 'city');
$inputParameters = array();
foreach ($fields as $field) {
// don't forget to validate the fields values from $_POST
if (!empty($_POST[$field])) {
$inputParameters[$field] = '%' . $_POST[$field] . '%';
}
}
$where = implode(' OR ', array_map(function($item) {
return "`$item` LIKE :$item";
}, array_keys($inputParameters)));
$search = $db->prepare("SELECT `id`, `name` FROM `users` WHERE $where");
$search->execute($inputParameters);
foreach ($search->fetchAll(PDO::FETCH_ASSOC) as $row) {
var_dump($row);
}
You can do it like this
$q = $_POST['q'];
$query = "SELECT `id`, `name` FROM `users` WHERE ";
// loop over submitted input keywords
foreach($keywords as $keyword){
$query .= $keyword . " LIKE ? ";
}
$sql=$db->prepare($query);
// loop over submitted input values array
foreach($values as $k => $value){
$sql->bindParam($k+1, '%'.$value.'%');
}
$sql->execute ();
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.
I've made a function to query the database. This function takes an array, the id of the user I want to update
and a query operation.
if the query operation is UPDATE
if you look at the code below, would this be a good coding practice or is this bad code?
public function query($column, $search_value, $query_operation = "SELECT"){
if(strtoupper($query_operation == "UPDATE")){
$query = "UPDATE users SET ";
if(is_array($column)){
$counter = 1;
foreach($column as $key => $value){
if($counter < count($column)){
$query .= $key . ' = ?, ';
}else{
$query .= $key . ' = ? ';
}
$counter++;
}
$query .= "WHERE id = ?";
$stmt = $this->database->prepare($query);
$counter = 1;
foreach($column as $key => &$value){
$stmt->bindParam($counter, $value);
$counter++;
}
$stmt->bindParam($counter, $search_value);
if($stmt->execute()){
$stmt = $this->database->prepare("SELECT* FROM
users WHERE id = ?");
$stmt->bindParam(1, $search_value, PDO::PARAM_INT);
$stmt->execute();
return $this->build_array($stmt);
}
}
}
}
would love to hear some feedback.
I would NOT mix SELECT and UPDATE in the same function.
The following update function uses arrays for column names and values $columnNames & $values using unnamed parameters.
function update($tableName,$columnNames,$values,$fieldName,$fieldValue){
$sql = "UPDATE `$tableName` SET ";
foreach($columnNames as $field){
$sql .= $field ." = ?,";
}
$sql = substr($sql, 0, -1);//remove trailing ,
$sql .= " WHERE `$fieldName` = ?";
return $sql;
}
As table and column names cannot be passed as parameters in PDO I have demonstrated whitelistng of table names.
$tables = array("client", "Table1", "Table2");// Array of allowed table names.
Also array_push()to add value for last parameter (WHERE) into $values array
Use
if (in_array($tableName, $tables)) {
$sql = update($tableName,$columnNames,$values,$fieldName,$fieldValue);
array_push($values,$fieldValue);
$STH = $DBH->prepare($sql);
$STH->execute($values);
}
You can use similar technique for SELECT