PDO Update not updating db - php

I can't get this code to update my, mysql database.
$SQL = $odb -> prepare("UPDATE `LB` SET `running` = `running` + 1 WHERE `url`= :url");
$SQL -> execute(array(":url"=> $url ));
May someone please help, I have searched for this and couldn't find something like this.

Don't do :url in your array, there is no need for it.
You can also use a question mark in place of your =:url like so:
url=?
Then in your array, you can either place a direct value:
$SQL->execute(array($url));
Or you can bind values incrementally:
$SQL->bindValue(1, $url, PDO::PARAM_INT);
$SQL->execute();
Except, instead of using PDO::PARAM_INT, you would use your own parameters...
So I'm guessing in your instance you would use PDO::PARAM_STR
Hopefully this helps :)

Related

UPDATE statement not working when using binding

I've got an issue regarding my UPDATE statement. When I want to update a column, it just doesn't let me to do that.
I tried to use a binded value for updating the column, I expected for it to change it but it didnt do that.
I wanted it to update the column which was the thing that I expected, but it didnt work.
Here's the code that I am struggling with:
$updatecolor = $conn->prepare("UPDATE avatar SET :part=:color WHERE user_id=:id");
$updatecolor->bindParam(':part', $part, PDO::PARAM_STR);
$updatecolor->bindParam(':color', $color, PDO::PARAM_STR);
$updatecolor->bindParam(':id', $myu->id, PDO::PARAM_INT);
$updatecolor->execute();
You can't bind param the name of a column. Perhaps use if statements to do this correctly.
if($part == "soandso"){
$updatecolor = $conn->prepare("UPDATE avatar SET soandso=:color WHERE
user_id=:id");
$updatecolor->bindParam(':color', $color, PDO::PARAM_STR);
$updatecolor->bindParam(':id', $myu->id, PDO::PARAM_INT);
$updatecolor->execute();
} elseif($part == "soandso2"){
// you get the idea

MySQL returning PDO placeholder names

There's a [similar post][1], but without a solution.
The following code is resulting in a MySQL query containing the placeholder names:
$the_image_itself = "abcde123def.jpg";
$title = "A Book";
$description = "Something to Read";
$the_image_itself = "%".$the_image_itself;
$stmt = $db->prepare("UPDATE nky_posts SET `post_title`=:title, `post_content`=:description WHERE `guid` LIKE :the_image_itself");
$stmt->bindParam(':title', $title);
$stmt->bindParam(':description', $description);
$stmt->bindValue(':the_image_itself', $the_image_itself, PDO::PARAM_STR);
$stmt->execute();
$stmt->debugDumpParams();
echo "<hr/>";
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$affected_rows = $stmt->rowCount();
The result looks like:
start SQL: [105] UPDATE nky_posts SET `post_title`=:title,
`post_content`=:description
WHERE `guid` LIKE :the_image_itself
Params: 3 Key:
Name: [6]
:title paramno=-1
name=[6] ":title"
is_param=1 param_type=2
Key: Name: [12] :description
paramno=-1 name=[12] ":description"
is_param=1 param_type=2
Key: Name: [17] :the_image_itself paramno=-1
name=[17] ":the_image_itself"
is_param=1 param_type=2
This is the object call:
try{
$db=new PDO('mysql:host=localhost;dbname=viewingr_ssdevwp; charset=utf8',$db_username,$db_password);
}
catch(PDOException $e){
echo 'Error connecting to MySQL!: '.$e->getMessage();
exit();
}
I don't know where you got the impression that debugDumpParams() will display the raw SQL query -- it will not. When using parameterized queries, you create a prepared statement at the database, and then send the parameter values alone. They are not sent together, meaning there's no way print the raw SQL query.
debugDumpParams() will only display the list of parameters, their names, types etc. but not their values. One thing you can do, however, is to inspect your MySQL query log to see the raw SQL query that was executed.
Once you've found the logs, you can use the following command to see the recently executed queries (provided you have SSH access):
$ sudo tail -f /usr/local/mysql/data/yourQueryLog.log
The above path is just an example. The actual path might be different on your system.
Well the "answer" is posted below, but the real answer is that I should have ceased banging my head against this problem and come back to it at a later date, which seems to be one of the most difficult things for me to do. At one point in my obsession I discovered a mysterious <br/> followed by some whitespaces in one of the placeholder values. I ended up doing substr($var, 0, -6) on the variable to remove the anomaly until noticing that I had inadvertently concatenated a <br/> to the end of the line that populated the variable; .<br/> - probably when deleting a line of output code for testing.
I was on the line with hostMonster tech support to try and get to MySQL logs because people say that that is the only place one can find out exactly WHAT MySQL is "seeing" when you use placeholders, but they don't log MySQL queries, because the file would be in the terrabytes.
At 3 or 4 am, I gave up.
Came back to it with a fresh head today and went through the following steps confirming each worked:
Create a simple SELECT statement without WHERE or placeholders:
$sql = "SELECT * FROM nky_posts";
Add a WHERE clause using "=" (not LIKE) with variable being something literal I know is in the DB:
$the_image = "image_url_from_phpMyAdmin";
$sql = "SELECT post_title FROM nky_posts WHERE guid = $the_image";
Substitute the literal variable with a single placeholder holding a known value:
$the_image = "image_url_from_phpMyAdmin";
$stmt->bindParam(':the_image', $the_image, PDO::PARAM_STR);
$sql = "SELECT post_title FROM nky_posts WHERE guid = :the_image";
Add the LIKE instead of = (remembering to concatenate placeholder variable with "%")
$the_image = "%" . $the_image . "%";
$stmt->bindParam(':the_image', $the_image, PDO::PARAM_STR);
$sql = "SELECT post_title FROM nky_posts WHERE guid LIKE :the_image_itself";
Replace the "known" variable with dynamic variable (from XML result in this case):
basename($oBookNode->getElementsByTagName('actual-link')->item(0)->nodeValue);
(Using basename() function to return just the image name from URL string in wordpress database)
Finally replace the SELECT statement with my UPDATE statement, adding two additional placeholders to hold the variables to be inserted. Final code:
$sql = "UPDATE nky_posts SET post_title=:title, post_content=:description WHERE guid LIKE :the_image";
$stmt = $db->prepare($sql);
//foreach loop begins here
foreach ($oDOM->getElementsByTagName('item') as $oBookNode)
{
$the_image = basename($oBookNode->getElementsByTagName('actual-link')->item(0)->nodeValue);
$title = $oBookNode->getElementsByTagName('title')->item(0)->nodeValue;
$description = $oBookNode->getElementsByTagName('actual-content')->item(0)->nodeValue;
//concat % to variable for LIKE clause (probably only needed first one in this case, but...)
$the_image = "%" . $the_image . "%";
$stmt->bindParam(':title', $title, PDO::PARAM_STR);
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
$stmt->bindParam(':the_image_itself', $another_image_itself, PDO::PARAM_STR);
$stmt->execute();
//end foreach loop
}
Thanks for the help, everyone.
The output from the debugDumpParams function call looks right.
That debugDumpParams function doesn't display the values of the bind parameters; it only shows the SQL text along with the placeholder names/positions, and their respective datatypes.
I'm not sure I understood the question you asked.
There's no need to invoke the fetchAll method on stmt, since it is an UPDATE statement.
Note that for rowCount, MySQL returns the number of rows that were actually changed by the statement, not the number of rows matched. That is, if the values in the columns being set were already set to the specified value, then MySQL doesn't "count" that row as being affected.

Code for Updating MySQLI PHP

A few keep telling me that my code for updating data in my mysqli query is extremely insecure. Actually, several people on this site. So I would like to know what they say would secure my code below so it is secure when updating my database. I would like to know how the would secure my mysqli query.
Okay, in my code for my database entries, this is what I do. Let me start by saying that I always send via POST method to avoid browser url complications.
When I get the POST data, this is my code.
$ID = 1;
$DATA = htmlentities(addslashes($_POST['data']));
$FIELD = "lifename";
$DBQUERY = "UPDATE `lifetable` SET `$FIELD` = '$DATA' WHERE `id` = $ID";
$DBRESULT = $MYSQLI->query($DBQUERY);
I am currently using this on my local site.
How is this unsafe if I have escaped all quotes, all slashes, all ampersands (from javascript through ajax) and all semi colons? How is this vunerable?
So can you tell me what I should change when adding information to my database.
Thanks
PS ... I am using mysqli and will continue to use it. Thanks
A few suggested that I change from mysqli to pdo, but I am not willing to completely 100% change how I access data from my databases. Someone posted another link before about prepare and bind_param and this is what I am going to use. So thank you.
This is now my code, and binding params is supposed to make it so that each param is only for the one part of my query and can not be for anything else, nothing else at all.
$DBQUERY = "UPDATE `lifetable` SET `lifename` = ? WHERE `id` = ?"; // EACH ? IS A PART OF bind_param BELOW IN ORDER AFTER TYPE.
$STMT = $MYSQLI->prepare($DBQUERY);
$STMT->bind_param('si', $DATA, $ID); // THIS MAKES SURE THAT THE VARIABLES ARE ONLY USED FOR THERE PLACE HERE AND NOTHING ELSE. ? in order.
$DATA = htmlentities($_POST['data']); // I STILL USE MY CODE HERE TO REMOVED ANY OTEHR CHARACTERS, JUST INCASE. AND BEFORE IT GETS HERE, IT USES encodeURIComponent TO OUTPUT FROM AJAX.
$ID = $COLUMN[1];
$STMT->execute();
$STMT->close();
My code worked before and it works now, just more secure, or so I am told.
Use PDO Class like:
$db = new PDO('mysql:host=localhost;dbname=<SOMEDB>', '<USERNAME>', 'PASSWORD');
$query = $db->prepare('UPDATE `lifetable` SET :FIELD = :DATA WHERE `id` = :ID');
$query->execute(array(
':FIELD' => $field,
':DATA' => $data,
':ID' => $id
));
$query->commit();
For more info Are there good tutorials on how to use PDO?
i think your security lies in the SQL injection, and the best way i know to make the query secure is using mysql_real_escape_string on the var. Here an example taken from php.net
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$city = $mysqli->real_escape_string($city);
$mysqli->query("INSERT into myCity (Name) VALUES ('$city')")
you can apply the same procedure to your query
$ID = 1;
$DATA = $MYSQLI->real_escape_string($_POST['data']));
$FIELD = "lifename";
$DBQUERY = "UPDATE `lifetable` SET `$FIELD` = '$DATA' WHERE `id` = $ID";
$DBRESULT = $MYSQLI->query($DBQUERY);
I edited the above because I forgot the quotes for lifename in my question. They should be there as they are in my original code.
now tour query should be secure :D
here the reference to php.net documentation :
http://cn2.php.net/manual/en/mysqli.real-escape-string.php

PDO Multiple Execution Issues

I have two inserts on a processing page. The first works without a hitch. The second will not even activate. I even tried putting a PDO query to see if it would work but still nothing.
$cpinsert = $db->prepare('insert into Chatposts values (0, :chatid, :name, :url, :text, now(), :ipaddress, 0)');
$cpinsert -> bindParam(':chatid', $chatroomid, PDO::PARAM_INT);
$cpinsert -> bindParam(':name', $name, PDO::PARAM_STR);
$cpinsert -> bindParam(':url', $url, PDO::PARAM_STR);
$cpinsert -> bindParam(':text', $text, PDO::PARAM_STR);
$cpinsert -> bindParam(':ipaddress', $ipaddress, PDO::PARAM_STR);
$cpinsert -> execute();
// Needs an error checker
$cpid = $cpinsert ->lastInsertID();
$cpinsert->closeCursor();
^ That works fine, though I don't know about the lastinsertid since I cannot test it.
\V/ Nothing in there will execute no matter what I try. Something is preventing anything there from executing or I didn't close the above's connection properly.
// Targets Insert
//if (isset($target)):
$query = "insert into Targets values (9,'rommel')";
$db->query($query);
$targetinsert = $db->prepare('insert into Targets values (:cpid,:tname)');
foreach ($target as $tname):
$targetinsert -> bindParam(':cpid', $cpid, PDO::PARAM_INT);
$targetinsert -> bindParam(':tname', $tname, PDO::PARAM_STR);
endforeach;
$targetinsert -> execute();
//endif;
I have tried everything I know of and no luck. It is quite possible I did a minor mistake since I am new to PDO. Closecursor didn't seem to do anything either when I added it in.
You said you need to do execute many inserts, but for some reason you are executing your query only once.
Also, please remove these try..catch things from your code - they are the reason why you have no idea what's going wrong
I had to recreate a half functional model of my page but I found the problem, it was lastinsertid(). I was applying a PDOstatement class on a PDO class.
Before:
$cpid = $cpinsert->lastInsertID();
After:
$cpid = $db->lastInsertID();
I just had to call the Database instead of the prepare with that line of code.

mysqli_stmt to return a result object

When querying using mysqli_stmt::prepare() and execute(), it will not return the result set. But we need to access using the mysqli_stmt:fetch() on the stmt object. There is one function in the php manual called mysqli_stmt::get_result() that will return the result set into a variable we define, but when I use it, it gives me undefined method error. The manual say it is probably in SVC which I am not sure what.
The codes:
$conn = new mysqli(DB_HOST,DB_USERNAME,DB_PASSWORD, DB_NAME);
$stmt = $conn->stmt_init();
$stmt->prepare("select * from users where u_id = ? ");
$stmt->bind_param('s', $param);
$stmt->execute();
Edit :
I know I can use bind_result() and fetch() function to retrieve the record like :
$stmt->bind_result($column1, $column2, $column3);
while ($stmt->fetch()) {
echo "Column 1: $column1\n";
echo "Column 2: $column2\n";
echo "Column 3: $column3\n";
}
But, my objective is to get the result set (the resource type object) after I execute, something like this:
$result = $stmt->execute();
so I can use the normal mysqli::fetch_object on the result set
$conn->fetch_object($result);
Is there any way to achieve this? thanks
Update:
The get_result function is exactly what I need, but it's not working on my PHP
Well, if you do not want to use mysqli_stmt::fetch() but mysqli_result::fetch_*(), I guess it will be a little cumbersome.
http://www.joekolba.com/node/2
Alternatively, use PDO.
I have done it in the following way:
$stmt->prepare("select * from users where u_id = ? ");
$stmt->bind_param('s', $param);
$stmt->execute();
$stmt->bind_result($columns['column_name1'], $columns['column_name2'], $columns['column_name3']);
while ($stmt->fetch()) {
$row = (object) $columns;
}
That comes quite near the FETCH_OBJECT method. You can access all the data of one row via $row->column_name1 etc. Of course you would have to update the associative columns-array, when you alter your table and change names. But it works quite well for me. Didn't want to switch to PDO - considering the fact I switched to MYSQLi just some days ago ;)
To enable the method mysqli_stmt::get_result(), you need to use the mysqlnd (MySQL Native Driver) extension: http://php.net/manual/en/book.mysqlnd.php
For some reason, this concrete method is not implemented with the more usual libmysqlclient. In my debian server (and also on my ubuntu desktop) this amounted to run:
sudo apt-get install php5-mysqlnd
You need to call bind_result to tell mysqli which variables should hold the columns. Then every time you call fetch, those variables will be automatically filled in, and you can access them like normal. See the code below (not sure if it works, ymmv).
$conn = new mysqli(DB_HOST,DB_USERNAME,DB_PASSWORD, DB_NAME);
if($stmt = $conn->prepare('select * from users where u_id = ?'))
{
$stmt->bind_param("s", $param);
$stmt->execute();
$stmt->bind_result($column1, $column2, $column3);
while ($stmt->fetch()) {
echo "Column 1: $column1\n";
echo "Column 2: $column2\n";
echo "Column 3: $column3\n";
}
$stmt->close();
}

Categories