Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
$follow = strip_tags($_POST["follow"]);
$follow = addslashes($follow);
$follow = mysqli_real_escape_string($conn, $follow);
$sesid = $_SESSION["id"];
$rowid = $row['id'];
$followers = $conn->query("INSERT INTO followers (forid, fromid) VALUES ('$rowid', '$sesid'");
echo "<h3><center>Sucessfully followed!</center></h3>";
}
It doesn't seem to work. It doesn't throw any errors. I'm a new(er) PHP developer. Thank you!
STOP this madness... Do not insert values into a query, that's how bad things happen.
Also, add some error checking here and there, it's impossible to know what's wrong with the piece of code (or is it?):
Try something more like this:
$conn = new mysqli('localhost', 'root', 'password', 'db_name');
if ($conn->connect_errno) {
throw new Exception('Connection Error' . $conn->connect_err);
}
Now let's deal with the post data:
if(isset($_POST)) {
$follow = $_POST["follow"];
$sesid = $_SESSION["id"];
$rowid = $row['id']; // don't know where this is coming from
if($stmt = $conn->prepare("INSERT INTO followers (forid, fromid) VALUES (?, ?)") {
$stmt->bind_param('si', $follow, $sesid);
if(!$stmt->execute()) {
throw new Exception('Error! Could not execute query.');
}
$stmt->close();
} else {
throw new Exception('Could not prepare query!');
}
} else {
// Add a error checking here
throw new Exception('No post data');
}
Prepared statements will help you avoid anyone trying to insert undesired content into your query (SQL injection).
The way it works,
Prepare the query ($conn->prepare())
Note here that there are simple ? where the values would otherwise be. That's for our next step.
Bind the parameters of your query with $stmt->bind_param(). This will tell PHP where each value should go, starting at the second parameter position.
The documentation for the bind_param function: bool mysqli_stmt::bind_param ( string $types , mixed &$var1 [, mixed &$... ] )
A little explanation for the first param:
s - stands for string (the $follow, I assume is a string)
i - stands for integer. The session ID
Then, finally, execute the query ($stmt->execute()). That will do the hard work of adding the values to your database.
Explicitly close the connection to your database ($conn->close());
Read more on PHP's official documentation.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
A seemingly minor problem are bothering me, something that should have a simple solution. I am currently running a server and a database, the database which contains data that I want to use in a PHP request on a website. I have created a function in PHP that does the following:
function getUserID($val){
include("config.php");
$conn = new mysqli($dbservername, $dbusername, $dbpassword, $dbname) or die($conn);
$sql = "SELECT userid FROM users WHERE username=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $val);
$stmt->execute();
$result = $stmt->get_result();
if(getUserExist($val)){
$rowdata = mysqli_fetch_assoc($result);
$conn->close();
return $rowdata['userid'];
}
}
This works just fine.. HOWEVER. The returned data type, which is supposed to be an Integer ( 1, 2, 3, 4... etc. ), returns a value similar to an JSON object or int(1), depending on how I write it.
array(1) { ["userid"]=> int(4) }
I have tried:
$rowdata['userid']
$rowdata
How do I make the function return purely the integer value? When it is added to the database with following code-snippet:
...
$stmt = $conn->prepare("INSERT INTO users (user1, user2, user3) VALUES (?, ?, ?)");
$stmt->bind_param("isi", $user1, $user2, $user3);
$user1 = $_POST[getUserID($username)];
$user2 = $_POST['val2'];
$user3 = $_POST['val3'];
$stmt->execute();
$stmt->close();
}
$conn->close();
As mentioned, it retrieves data just fine, it is just the value that acts in an odd way. When this code is executed, $user1 or rather the final value within database has the value of NULL. (database accepts only integers in that slot).
It looks to me as if the problem does not lie in getUserID(), but in this line:
$user1 = $_POST[getUserID($username)];
What you're doing here is not setting $user1 to the value of getUserID() - instead, you're setting it to "the element in the $_POST array which has a key of whatever getUserID() returns". And there are very few scenarios where that makes sense.
I'm assuming the line you want to replace it with is
$user1 = getUserID($username);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a mySQLi prepared statement and a function I want to pass it to to check to see if the input meets the right format before executing it. I have determined in my actual code that if I move the $stmt->execute() statement just outside of the function that it works, but inside the function it does not. I know that an old school concatenated SQL string can be passed like this, but what is the right way to handle this with prepared statements?
function validateForm($stmt, $inputType){
// A bunch of stuff here to validate for $inputType.
$stmt->execute();
}
$editSQL = "UPDATE mytable SET input1 = ?, input2 = ?, input3 = ? WHERE thisID = ?";
$stmt = $conn->prepare($editSQL);
$stmt->bind_param('sibi', $input1, $input2, $input3, $thisID);
$input1 = $vPara[1][5];
$input2 = $vPara[2][5];
$input3 = $vPara[3][5];
$thisID = $_SESSION['thisID'];
validateForm($stmt, $inputType);
The specific error I get is:
Fatal error: Call to a member function execute() on a non-object
I don't see why it could potentially not work.
You mentioned that if you use execute outside of this function it works. So leave it the way it works because That's recommended due to Single responsibility principle.
Your validator should not be responsible for executing statements but
only for what its name says = validation.
The only thing that validator should do is to return true or false
and upon that decision, you should make execution or not
so change your code to the following:
<?php
function isFormValid($inputType)
{
// A bunch of stuff here to validate for $inputType.
if (//test cases) {
$validationResult = true;
} else {
$validationResult = false;
}
return $validationResult;
}
$editSQL = "UPDATE mytable SET input1 = ?, input2 = ?, input3 = ? WHERE thisID = ?";
$stmt = $conn->prepare($editSQL);
$stmt->bind_param('sibi', $input1, $input2, $input3, $thisID);
$input1 = $vPara[1][5];
$input2 = $vPara[2][5];
$input3 = $vPara[3][5];
$thisID = $_SESSION['thisID'];
if(isFormValid($inputType)) {
$stmt->execute();
} else {
//do error processing echo, trow exception etc
}
?>
Note that I changed the validator name, so now it really expresses what it does, instead of being called validateForm but actually doing also a statement execution.
So I'm making my own blog scripts using MYSQL and PHP.
I had the whole 'writing the blog to a database' thing working perfectly, until I realised that if you tried to write a blog with speech marks, this would prevent the INSERT statement from working (obviously - the speechmarks were ending the SQL statement).
So I tried to use real_escape_string, and now the INSERT doesn't work even if you exclude quotes.
I tried using:
sqlstate
in order to find out the issue, and it returned "42000" - which, after googling for a little bit, refers to a syntax error, which doesn't make much sense as there is no syntax error before the use of real_escape_string.
Also, I'm now getting this error:
Call to a member function close() on a non-object in /postarticle.php on line 37
Which refers to the close() call in the ELSE statement.
Please may you help? Been going round in circles for a while. Here is my code:
<?php
$host = 'CENSORED';
$user = 'CENSORED';
$pass = 'CENSORED';
$db = 'CENSORED';
$connection = new mysqli($host,$user,$pass,$db);
$_SESSION["article"] = $_POST["article"];
$date_of_blog = getdate();
$article = ($_SESSION["article"]);
$sql1 = "SELECT * FROM `Blogs`";
$res1 = $connection->query($sql1);
$newrows = $res1->num_rows + 1;
$sql2 = "INSERT INTO Blogs(BlogID, Blog_Contents, D_O_B) VALUES ('$newrows','$article','$date_of_blog')";
$sql2 = $connection->real_escape_string($sql2);
$res2 = $connection->query($sql2);
if ($res2->num_rows == $newrows)
{
$res->close();
$connection->close();
header( 'Location: adminpanel.php' );
}
else
{
echo ($connection->sqlstate);
$connection->close();
$res->close();
}
exit();
?>
Also, on a side note, the getdate() call that I've got has never worked. In the database every blog post comes up as:
0000:00:00 00:00:00
EDIT:
Issue is now solved. Find the functional code below:
<?php
$host = 'CENSORED';
$user = 'CENSORED';
$pass = 'CENSORED';
$db = 'CENSORED';
$connection = new mysqli($host,$user,$pass,$db);
$_SESSION["article"] = $_POST["article"];
$article = ($_SESSION["article"]);
$article = $connection->real_escape_string($article);
$sql1 = "SELECT * FROM `Blogs`";
$res1 = $connection->query($sql1);
$newrows = $res1->num_rows + 1;
$sql2 = "INSERT INTO Blogs(BlogID, Blog_Contents, D_O_B) VALUES (\"$newrows\",\"$article\",CURDATE())";
$res2 = $connection->query($sql2);
if ($res2 != false)
{
header( 'Location: adminpanel.php' );
}
else
{
echo ($connection->sqlstate);
}
$connection->close();
$res->close();
exit();
?>
I'm very sorry if these questions are basic and annoy the professionals around here; I've tried to follow the guidelines and I've googled for a while etc. I just haven't found any solutions that match my issue(s).
Thankyou for your time.
There are a number issues with the code as originally posted. Chiefly, the cause of the two issues you initially identified is a misuse of mysqli::real_escape_string(). It needs to be called on each variable individually which appears in the code. So instead of calling it on the whole statement, it must be called multiple times for multiple variables like:
$article = $connection->real_escape_string($connection);
The failure of the query due to incorrect quoting (due to real_escape_string()) is the reason for the error message calling close().
As ascertained in the comments, you are using num_rows + 1 to validate that one new row has been inserted based on the previous number of rows returned. This is problematic for a few reasons. Mainly, it exposes a race condition wherein a row may be inserted from two sessions at once and one or both will fail because the expected value for $newrows doesn't match. Really BlogID should be an auto_increment column in your database. That eliminates the need for any logic around it whatsoever. You don't even need to include it in the INSERT because it will be automatically incremented.
That also completely eliminates the need for the first SELECT statement.
Substituting MySQL's native NOW() function for the date value, you can simplify the statement to:
INSERT INTO Blogs (Blog_Contents, D_O_B) VALUES ('$article', NOW())
To test success or failure of the insert, you just need to verify that its variable is not false.
Putting this together, your code can be reduced as:
if (!isset($_POST['article'])) {
// exit or handle an empty post somehow...
}
$connection = new mysqli($host,$user,$pass,$db);
$_SESSION["article"] = $_POST["article"];
// Escape $article for later use
$article = $connection->real_escape_string($_SESSION["article"]);
// Only an INSERT is needed. $article is already escaped
$sql = "INSERT INTO Blogs (Blog_Contents, D_O_B) VALUES ('$article', NOW())";
// Run the query
$res = $connection->query($sql);
// Test for failure by checking for a false value
if ($res) {
// The connection & resource closure can be omitted
// PHP will handle that automatically and implicitly.
header( 'Location: adminpanel.php' );
// Explictly exit as good practice after redirection
exit();
}
else {
// The INSERT failed. Check the error message
echo $connection->error;
}
This should bring your current code into working order. However, since you're learning this it is an excellent time to begin learning to use prepared statements via prepare()/bind_param()/execute() in MySQLi. This is a recommended best practice to prevent SQL injection, although using real_escape_string() works as long as you use it correctly and never forget.
See How can I prevent SQL injection in PHP for examples.
But it would look like:
// connection already established, etc...
// Prepare the statement using a ? placeholder for article
$stmt = $connection->prepare("INSERT INTO Blogs (Blog_Contents, D_O_B) VALUES (?, NOW())");
if ($stmt) {
// bind in the variable and execute
// Note that real_escape_string() is not needed when using
// the ? placeholder for article
$stmt->bind_param('s', $_SESSION['article']);
$stmt->execute();
// Redirect
header( 'Location: adminpanel.php' );
exit();
}
else {
echo $connection->error;
}
You need to apply the real_escape_string function to the variables not the entire SQL string.
$sql2 = "INSERT INTO Blogs(BlogID, Blog_Contents, D_O_B) VALUES ('".$connection->real_escape_string($newrows)."','".$connection->real_escape_string($article)."','".$connection->real_escape_string($date_of_blog)."')";
The purpose is to remove anything that might be misinterpreted as query functions by MySQL, but there are parts of the query that you obviously want to be interpreted as such.
I am trying to write a function that is supposed to receive any MySQL statement and apply it,
The basic idea is not to repeat needed code to write to Database, well what is needed to connect to Database is creating new PDO object, starting a transaction and preparing a statement, binding values to it, executing it,
so every time I want to access the Database I don't have to repeat these steps,
Here is a function that does that :
==============================================================================================
protected function applyQuery($statement, $bindparameters , &$values , $selectStatement, &$result){
try{
$dbh = DataBase::setConnection();// new PDO("MySQL= .....");
$dbh->beginTransaction();
$stmt = $dbh->prepare($statement);
if($bindparameters == true){
foreach($values as $key => $value){
$stmt->bindValue($key, $value);
}
}
$stmt->execute();
$dbh->commit();
if($selectStatement == TRUE){
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}catch (PDOException $e){
$dbh->rollBack();
throw DataBase::$Errors[0];
}
}
============================================================================================
$statement = the desired statement (e.g 'SELECT * from users WHERE username = :username')///
$bindparameters = do we need to bind values (in this examples yes) so its value TRUE///
&$values = array by reference in this case equals = (':username' => 'User');///
$selectStatement = tells if using SELECT in statement ,in this case TRUE///
$result = array by reference in this case the final fetch result will be stored in it///
so in this example we get the following call to the function :
applyQuery('SELECT * from users WHERE username = :username', TRUE ,array(':username' => 'User') , TRUE , result )
My question is : will this code work ?
is the logical sequence of what it does and should do make sense ?
whats the difference between $stmt->execute and $dbh->commit ?
is omitting any line will cause failure to achieve the desired result
Please understand that I did lookup what is PDO and read a lot but unable to answer these questions!
I'm having a slight issue with prepared statements for PHP and MySQLi. My code takes POST data, prepares a statement and then binds the POST data to the query. After this it executes, seemingly without error, but the statement clearly doesn't ever get executed correctly since no database changes occur.
A quick overview of my problem:
I'm using MySQLi and prepared statements.
I've updated some previous PHP/MySQLi code that was not using prepared statements.
Since updating, a problem has occured with $query->execute().
Code:
if($query = $this->mysqli->prepare("UPDATE article SET copy = ?, title = ?, alias = ?, description = ?, category = ?, category_id = ?, author = ?, permission = ?, mode = ?, comments = ?, revised = ?, frequency = ?, priority = ? WHERE id = ?"))
{
if
(
$query->bind_param
(
"sssssdsssssssd",
$_POST['edit_article'],
$_POST['edit_title'],
$_POST['edit_alias'],
$_POST['edit_description'],
$_POST['edit_category'],
$result['id'],
$_POST['edit_author'],
$_POST['edit_permission'],
$_POST['edit_mode'],
$_POST['edit_comments'],
$date_time,
$_POST['edit_frequency'],
$_POST['edit_priority'],
$id
)
)
{
if($query->execute())
{
echo $this->mysqli->error; // does nothing.
// These statements print to the screen successfully with the correct values.
echo $_POST['edit_frequency'] . "<br />";
echo $_POST['edit_priority'] . "<br />";
//$_SESSION['article_edited'] = true;
// die;
//exit(header("Location: " . __MANAGER__ . $_POST['edit_alias']));
}
else
{
$_SESSION['article_edited'] = false;
exit(header("Location: " . __MANAGER__ . $_POST['edit_alias']));
}
}
}
else
{
$_SESSION['article_edited'] = false;
exit(header("Location: " . __MANAGER__ . $_POST['edit_alias']));
}
Could anybody perhaps explain a better way to debug this code? It makes no sense to me since I check whether the execute() function works with if($query->execute()) and it's successful. Assuming of course the problem does not lie with the execute function, but elsewhere. The problem can't be the POST data since it validates fine with:
if
(
$_POST['foo'] && isset($_POST['foo']) &&
$_POST['bar'] && isset($_POST['bar'])
)
{
// Statements.
}
I am clueless.
EDIT
I would like to note I echo the values of 2 particluar POST vars since those were the ones I added in when updating the code. It has since stopped working. Also note I have used print_r($_POST) and all POST vars are set and contain values.
Your update will return success IF there is no error at SQL level. Note that NOT finding candidate rows to updates is NOT a SQL error. That is a logical error/expected condition. If failure to find a row to update is an error condition for your code, then you will need to modify your error check to include a check for that.
if($query->execute())
{
if($mysqli->affected_rows == 0)
// some logical error
Problem has been solved.
The error was, as expected, not caused by a malfunction or faulty logic, rather an unchanged variable $id, that should have been converted to $_POST['id']. For those that read this in the future, it may be worthwhile noting that Amit Agrawal's reply is actually an important one.
Please bear in mind that the SQL statement was not in error, it just so happened that no rows were affected since the variable $id was not set or initialised. Therefore, the appropriate course of action would be something along the lines of:
if($query->execute())
{
if($this->mysqli->affected_rows == 0)
{
// Appropriate action (such as raising an error), e.g.,
die("No rows were affected");
}
else
{
// Appropriate action.
}
}
else
{
die("Query could not be executed.");
}