1

I keep receiving some variant of this error message:

Warning: PDO::exec(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@email.com",5,2)' at line 1 in C:\xampp\htdocs\donations\index.php on line 31

The PHP it is referring to is this:

$db->exec("INSERT INTO donations(name, email, donation_amount, item_id) VALUES(\"" . $_POST['name'] . "\"," . $_POST['email'] . "\"," . $_POST['amount'] . "," . $_POST['radioButtons'] . ");");

Am I not escaping correctly or do I have too many quotes? Any help is appreciated!

peterm
  • 91,357
  • 15
  • 148
  • 157
user2766423
  • 167
  • 1
  • 2
  • 9
  • 4
    You're not escaping your inputs at all.... try finding a tutorial that teaches the use of prepared statements/bind variable otherwise your site is going to be hacked pretty quickly – Mark Baker Sep 10 '13 at 20:19
  • atleast assign it to a variable and use those variable – zod Sep 10 '13 at 20:20
  • @zod Yeah because that is totally a solution for OPs issues right? Also since when is an array not a variable? – PeeHaa Sep 10 '13 at 20:21
  • @Pee Its not a solution , thats why i put it as comment ..Yee Haa Pee Haa – zod Sep 10 '13 at 20:26
  • Ok I apologize for the apparently old approach to my code. This was partially made up for me from a friend to help me learn a bit more about databases. If it helps, I can make another question with more code. I will look up more about prepared statements. – user2766423 Sep 10 '13 at 20:28
  • @zod It indeed is not a solution. I am really wondering *what* it is exactly? – PeeHaa Sep 10 '13 at 20:31

3 Answers3

4

You're already on a right track using PDO. Now the next step is to use it properly by utilizing prepared statements.

That being said your code might look something like this:

//TODO Check, validate, sanitize your input...
$name = $_POST['name'];
$email = $_POST['email'];
$donation_amount = $_POST['amount'];
$item_id = $_POST['radioButtons'];

try {
    $db = new PDO('mysql:host=localhost;dbname=your_db_name', 'user', 'password');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    //Construct your query with placeholders
    $sql = "INSERT INTO donations (name, email, donation_amount, item_id) 
            VALUES (?, ?, ?, ?, ?)";
    //Prepare your query
    $query = $db->prepare($sql);

    //Execute it passing parameters
    $query->execute(array($name, $email, $donation_amount, $item_id));

} catch (PDOException $e) {
    echo "Exception: " . $e->getMessage(); //TODO better error handling
}
$query = null;
$db = null;

Further reading:

Community
  • 1
  • 1
peterm
  • 91,357
  • 15
  • 148
  • 157
  • 1
    Did I just see the SQLi police answer this question? +1 brave sir – PeeHaa Sep 10 '13 at 20:23
  • Ok I will give this a go. Thank you for the help. I'm literally stunned by the amount of information here. I'll work on this and will be posting back. – user2766423 Sep 10 '13 at 20:39
  • @user2766423 You're quite welcome. Good luck :) Do not hesitate to ask a follow up question. – peterm Sep 10 '13 at 20:43
1

Your problem is actually a problem with escaping quotes. If you would have used more standard single quotes for enclosing values in SQL statement you probably would have noticed this more easily, but you do not currently have an opening quote before your email value.

I would highly suggest use of prepared statements like this:

$query = 'INSERT INTO donations (name, email, donation_amount, item_id) VALUES (:name, :email, :amount, :radioButtons)';
$sth = $db->prepare($query);
$sth->execute(array(
    ':name' => $_POST['name'],
    ':email' => $_POST['email'],
    ':amount' => $_POST['amount'],
    ':radioButtons' => $_POST['radioButtons']
));

Of course this doesn't should proper error handling that you would also want to put in place along the way.

This prepared statement will protect you against SQL injection, and also has the benefit of making you SQL much more readable by eliminating the need for quotes.

I actually prefer to use the more verbose method of binding all the parameters rather than passing an array of values to execute. This allows you to specify the input type explicitly (i.e. integer, string, etc.). So based on the assumption that the last two values are integers taht might look like this:

$query = 'INSERT INTO donations (name, email, donation_amount, item_id) VALUES (:name, :email, :amount, :radioButtons)';
$sth = $db->prepare($query);
$sth->bindParam(':name', $_POST['name'], PDO::PARAM_STR);
$sth->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
$sth->bindParam(':amount', $_POST['amount'], PDO::PARAM_INT);
$sth->bindParam(':radioButtons', $_POST['radioButtons'], PDO::PARAM_INT);
$sth->execute();

I didn't write it this way initially, as I think that, for whatever reason, the PHP community largely gravitates towards passing the value via array to execute(). They also more commonly tend to use ? placeholders rather than named placeholders, but, to me, this is just being lazy. I mean are you really saving that much time in writing a few extra characters to sacrifice clarity of the code?

Mike Brant
  • 70,514
  • 10
  • 99
  • 103
  • 1
    @PeeHaa Actually it does. The original problem is that he doesn't have an SQL quote character at the start of the email value. By using a prepared statement he can more clearly write the query and not have to worry about escaping quotes (though he should have used single quotes around the values in this case). – Mike Brant Sep 10 '13 at 20:34
  • 1
    boooooo you edited it before you posted your comment. That's cheating – PeeHaa Sep 10 '13 at 20:37
  • 1
    @PeeHaa Actually I didn't. I realized your comment was on point in regards to me not explicitly stating the reason for his original problem. I mentioned the reason in the comment and then decided I should add to answer as well. :) – Mike Brant Sep 10 '13 at 20:47
0

Add spaces between the field/table names and parantheses

INSERT INTO donations (name...) VALUES (...)

Also, use single quotes ' ' around values.

VALUES ( '" . $_POST['name'] . "' )

Also, never inject $POST data directly into your SQL queries. This is begging for SQL Injection. And by all means, go learn PDO/Prepared Statements and stop using mysql functionality. Its dead.

Rottingham
  • 2,593
  • 1
  • 12
  • 14
  • Is what not there? His question displays INSERT INTO DONATIONS(name, email) Sql thinks you want to insert into the table named donations(name, edit...) – Rottingham Sep 10 '13 at 20:21
  • @Rottingham The OP is clearly already using PDO based on the error message, not mysql extension. That being said, he should be using a prepared statement for this. – Mike Brant Sep 10 '13 at 20:23
  • @Mike He used PDO to create a connection but clearly isn't using it for what its worth. He is treating it like mysql_ – Rottingham Sep 10 '13 at 20:24
  • @rottingham you try yourself and find the sql will execute without your spaces or not – zod Sep 10 '13 at 20:24