I know this topic has been discussed a lot in stackoverflow but I've read all topics I couldn't find a solution.
I've got this function which should update a mysql database. It justs do not do nothing, and do not show any errors. As you see I use PDO. I've seen lots of question similar to mine in stackoverflow, and tried their solution but none of them seems to work.
I've checked that all variables that I pass to this function arrive and are correct.
public function updateValues($coreID, $table, $name, $time){
if ($this->databaseConnection()) {
$query_edit_user_name = $this->db_connection->prepare("UPDATE :tableT SET time = :timeT, name = :nameT WHERE id = :coreID");
$query_edit_user_name->bindValue(':coreID', trim($coreID), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':tableT', trim($table), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':nameT', trim($name), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':timeT', trim($time), PDO::PARAM_INT);
$query_edit_user_name->execute();
}
}
I've been trying to add´´ or '' to different rows names or values but didn't worked. The only way it "works" is if there isn't a single PDO parameter:
$query_edit_user_name = $this->db_connection->prepare("UPDATE table1 SET time = '55', name = 'name1' WHERE id = 'core2'");
Any ideas?
You can't use a bind value or parameter for a table name.
$query_edit_user_name = $this->db_connection->prepare("UPDATE :tableT SET time...
^^^^^^^
Try this instead:
public function updateValues($coreID, $table, $name, $time){
if ($this->databaseConnection()) {
$query_edit_user_name = $this->db_connection->prepare("UPDATE `$table` SET time = :timeT, name = :nameT WHERE id = :coreID");
$query_edit_user_name->bindValue(':coreID', trim($coreID), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':nameT', trim($name), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':timeT', trim($time), PDO::PARAM_INT);
$query_edit_user_name->execute();
As has been pointed out in the comments, a dynamic table name is open to a possible injection, depending on where the table name is derived from.
Either, escape the table name before preparing the statement with something like:
$table = str_replace(array('\\',"\0" ,'`'), '', $table);
Or, use a whitelist method:
$allowed = array('table1', 'table2');
if (in_array($table, $allowed)) {
// prepare and execute query
}
Related
So I am attempting to write a generic sqlite insert that can be used no matter how many items a row has. This is for a single row, assumes all columns other than ID, which is set to autoincrementing integer, are assigned, and bindparam must be used. I have been attempting it like so:
Table Quarterbacks
ID---firstName---lastName
public static function insert($table, $values)
{
$pdo = new PDO('sqlite:testTable.sqlite');
$inputString = implode(",", $values);
$statement = $pdo->prepare("insert into $table values (:value)");
$statement->bindParam(':value', $inputString);
$statement->execute();
}
$new = array("Steve", "Young");
Query::insert("Quarterbacks", $new);
The idea being that the table will now add a new row, increment the ID, and add Steve Young. But I get the generic error that the prepare statement is false. I know my pdo is connecting to the database, as other test methods work. There's a lot of array related threads out there but it seems like they're much more complicated than what I'm trying to do. I'm pretty sure it has to do with it treating the single string as invalid, but it also won't take an array of strings for values.
Edit:I'm starting to lean towards a compromise like bash, ie provide a large but not infinite amount of function parameters. Also open to the ...$ style but I feel like that ends up with the same problem as now.
I was able to get this to work
$name = "('daunte' , 'culpepper')";
$cats = "('firstName', 'lastName')";
$statement = $pdo->prepare("insert into $table" .$cats ." values" .$name);
$statement->execute();
But not this
$name = "('reggie' , 'wayne')";
$cats = "('firstName', 'lastName')";
$statement = $pdo->prepare("insert into $table:cats values:name");
$statement->bindParam(':cats', $cats);
$statement->bindParam(':name', $name);
$statement->execute();
I'm trying to switch my sql to PDO but I'm having trouble getting even this simple query to return a value. Surely it can't be this difficult. I've done the same query the old fashioned way and it works perfectly as expected. The PDO version returns nothing. What's the trick here?
This first version returns the value I expect.
$customfieldid = 676;
$entityid = 9784549;
$entitytype = 'familyoverview';
$sql = "select value
from customfieldvalues
where customfieldid = ".$customfieldid."
and entityid = ".$entityid."
and entitytype = '".$entitytype."'";
$result = mysql_query($sql);
if($row = mysql_fetch_array($result)) {
$mysqlvalue = $row["value"];
echo "<br>mysql value: ".$mysqlvalue;
}
This PDO version returns nothing.
$sql = "select value
from customfieldvalues
where customfieldid = :customfieldid
and entityid = :entityid
and entitytype = :entitytype";
$stmt = $pdo->prepare($sql);
//$stmt->bindValue(':customfieldid', $customfieldid, PDO::PARAM_INT);
//$stmt->bindValue(':entityid', $entityid, PDO::PARAM_INT);
//$stmt->bindValue(':entitytype', $entitytype, PDO::PARAM_STR);
$stmt->bindValue(':customfieldid', 676, PDO::PARAM_INT);
$stmt->bindValue(':entityid', 9784549, PDO::PARAM_INT);
$stmt->bindValue(':entitytype', 'familyoverview', PDO::PARAM_STR);
$pdovalue = $stmt->fetchColumn();
echo "<br>pdo value: ".$pdovalue;
I've confirmed that I have a pdo database connection. I've tried using the third parameter and omitting the third parameter in the bindValue calls. I've also tried hardcoding the values in the bindValue calls vs passing them in but none of that makes any difference.
Your PDO code is missing a call to $stmt->execute(), so the query is never sent to the MySQL server and executed. Without executing the query, there can't be any results.
The code below makes a query and then loops through those results. I am having a hard time understanding what "?" is in that query and how to make "?" dynamic.
It assume that name = "?". I have changed ? to a variable I added in the function $ad_id and that still does not work. I basically need to query the DB only WHERE name = a variable. But this simple solution does not work. The commented line is what I replaced.
Any help will be greatly appreciated. Incase you are wondering this is the code I am trying to make dynamic and not just pulling all images in the table:
https://github.com/blueimp/jQuery-File-Upload/wiki/PHP-MySQL-database-integration
protected function set_additional_file_properties($file) {
parent::set_additional_file_properties($file);
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$ad_id = '1';
//$sql = 'SELECT `id`, `type`, `title`, `description` FROM `'
//.$this->options['db_table'].'` WHERE `name`=?';
$sql = 'SELECT id, type, title, description FROM '.$this->options['db_table'].' WHERE name = '.'$ad-id'.';
$query = $this->db->prepare($sql);
$query->bind_param('s', $file->name);
$query->execute();
$query->bind_result(
$id,
$type,
$title,
$description
);
while ($query->fetch()) {
if ($description == $ad_id){
$file->id = $id;
$file->type = $type;
$file->title = $title;
$file->description = $description;
};
}
}
}
In this example, the SQL query is using bound parameters. This means that you create the string for the SQL query, and put a placeholder in for each variable - the placeholder is the '?' character you mentioned. Then the following two lines:
$query = $this->db->prepare($sql);
$query->bind_param('s', $file->name);
The first line sends the query to the database, and the second line sends the parameters that need to be bound into the placeholder sites (where those question marks were in the query string). So if you want to change the variable that is inserted into the query, you should change the bind_param call.
Check out the documentation for bind_param, but basically the 's' specifies a string parameter, and the second argument is the variable itself.
Hopefully that gives you enough insight into what is going on here to change the code to do exactly what you want.
This has been driving me crazy, the issue is I cannot work out How i can get and set the cached data to be displayed within my view.
public function get_something($id, $account_name)
{
$sql = "SELECT one,two,three FROM table WHERE id = ? and account_name = ? ";
$key = md5("SELECT one,two,three FROM table WHERE id = $id and account_name = $account_name ");
$get_result = $this->Core->Core->Memcache->get($key);
if($get_result)
{
// How would I set the Data
}
else
{
$stmt = $this->Core->Database->prepare($sql);
$stmt->bind_param("is", $id, $account_name);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($one, $two, $three);
$stmt->fetch();
//Below is how i set the data
$this->Core->Template->set_data('one', $one);
//Set the Memcache
$this->Core->Memcache->set($key, $stmt, TRUE, 20);
}
So my question is how can I get and set the data from a prepared statement fetch within memcache?
Memcache is a key/value storage system with both the key and the value needing to be serialized. From the php.net page:
Remember that resource variables (i.e. file and connection descriptors) cannot be stored in the cache, because they cannot be adequately represented in serialized state.
It appears your sql statement is looking for three values in a single row. I'm no expert on mysqli, but this is kind of what you want to do:
public function get_something($id, $account_name){
$sql = "SELECT one,two,three FROM table WHERE id = ? and account_name = ? ";
$key = md5("SELECT one,two,three FROM table WHERE id = $id and account_name = $account_name ");
$get_result = $this->Core->Core->Memcache->get($key);
if($get_result){
return $get_result;//#1 just return it, the format is an array like what is being built below
}
else{
$stmt = $this->Core->Database->prepare($sql);
$stmt->bind_param("is", $id, $account_name);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($one, $two, $three);
$stmt->fetch();
//Below is how i set the data
$this->Core->Template->set_data('one', $one);//#2 I don't know what this line does or is for, presumably for something else besides memcache stuff, maybe it acts like return
//Set the Memcache
$array=array();//#3
$array[]=$one;
$array[]=$two;
$array[]=$three;
$this->Core->Memcache->set($key, $array, TRUE, 20);
//this is a function, do you want to return your values somewhere?
}
A few notes, #1 the answer to your question is simple, just return $get_result. It should be an array with three values. #2 I'm not familiar with this line, nor what it does. Is this how your "return" the values to your controller? If so, you'll want to mimick that line where I put the return inside the if #3 This is your problem. You can't save the $stmt variable in memcache, it's a mysqli object, not the data you want. You need to build an array and then save that array. And that should do it for you.
There are other nuances to do, you can loop on the returned values. You should check for mysql not returning anything. But this is the basic starting point to get this going.
Let me know if this works for you.
Thanks for looking. All helpful answers/comments are up voted.
In php, you can use NOW() like this:
mysql_query("INSERT INTO tablename (id, value, time_created)
VALUES ('{$id}', '{$value}', NOW())");
How can I do the same thing in PDO. When I bind like this, I get an error:
$stmt->bindParam(':time_added', NOW(), PDO::PARAM_STR);
Is it the PDO:PARAM_STR?
Because nobody has explicitly answered the question, I'll add the correct answer for the sake of completeness.
$stmt = $pdoDb->prepare('INSERT INTO tablename (id, value, time_created) VALUES (:id, :value, NOW())');
// either bind each parameter explicitly
$stmt->bindParam(':id', $id); // PDOStatement::bindValue() is also possibly
$stmt->bindParam(':value', $value);
$stmt->execute();
// or bind when executing the statement
$stmt->execute(array(
':id' => $id,
':value' => $value
));
Presuming your PDO statement is correct you could do something like this:
$date = date('Y-m-d H:i:s');
$stmt->bindParam(':time_added', $date, PDO::PARAM_STR);
None of the answers solve the question as I see it!
So there are some of my findings:
there is NO WAY how to force PDO to pass MySQL function call as a query value - so there is no way to do simple wrapper that will be able to use NOW() or any other function as passed values. Every time you need something like that, you need manually change the query, so the function call is part of the query string. :-(
I'm using function that tests given values for MySQL function I am using and modifies the query itself, but it is not a good solution to my opinion... :-}
This might be useful to some of you, maybe not. I was confronted with the same problem as Ollie Saunders was. I'm pretty new to php/mysql, and most of all PDO. I was able to solve the problem with the following:
$active = 0;
$id = NULL;
$query = "INSERT
INTO tbl_user(ID_user, firstname, lastname, email, password, active, create_date)
VALUES (?,?,?,?,?,?,NOW())";
if($stmt=$this->conn->prepare($query)) {
$stmt->bind_param('issssi', $id, $firstname, $lastname, $email, $password, $active);
$stmt->execute();
}
and guess what it works! Hope to have helped here. Any comments are welcome. Try it and tell me if it worked for you, or if you have any additions.
To answer Elmo's question, you can create a PDO wrapper that allows for SQL functions like NOW(). You just need to pass an additional argument with the columns that you want to use SQL functions for. Here's mine:
function pInsertFunc($action, $table, $values, $sqlfunctions)
{
global $pdb;
// There's no way to pass an SQL function like "NOW()" as a PDO parameter,
// so this function builds the query string with those functions. $values
// and $sqlfunctions should be key => value arrays, with column names
// as keys. The $values values will be passed in as parameters, and the
// $sqlfunction values will be made part of the query string.
$value_columns = array_keys($values);
$sqlfunc_columns = array_keys($sqlfunctions);
$columns = array_merge($value_columns, $sqlfunc_columns);
// Only $values become ':paramname' PDO parameters.
$value_parameters = array_map(function($col) {return (':' . $col);}, $value_columns);
// SQL functions go straight in as strings.
$sqlfunc_parameters = array_values($sqlfunctions);
$parameters = array_merge($value_parameters, $sqlfunc_parameters);
$column_list = join(', ', $columns);
$parameter_list = join(', ', $parameters);
$query = "$action $table ($column_list) VALUES ($parameter_list)";
$stmt = $pdb->prepare($query);
$stmt->execute($values);
}
Use it like this:
$values = array(
'ID' => NULL,
'name' => $username,
'address' => $address,
);
$sqlfuncs = array(
'date' => 'NOW()',
);
pInsertFunc("INSERT INTO", "addresses", $values, $sqlfuncs);
The query string that results looks like this:
INSERT INTO addresses (ID, name, address, date) VALUES (:ID, :name, :address, NOW())
other than NOW() i also utilize the "timestamp" type column and set its default to CURRENT_TIMESTAMP .. so i just pass nothing for that field and time is automatically set. maybe not exactly what ur looking for.