I’m having trouble converting this now() + INTERVAL INSERT statement to a PDO prepared statement with named placeholders.
When I bind the value using either 'now() + INTERVAL 3 DAY' or 'DATE_ADD(now(), INTERVAL 3 DAY)', it inserts 000’s instead of the correct datetime (0000-00-00 00:00:00)
This is what I was previously using:
$qry = "INSERT INTO password_reset(user_id, temp_password, expiry_date)
VALUES('$member_user_id','$temp_password', now() + INTERVAL 3 DAY)";
New PDO Statement:
$stmt = $conn->prepare('INSERT INTO password_reset (user_id, temp_password, expiry_date)
VALUES(:user_id, :temp_password, :expiry_date)');
$stmt->bindValue(':user_id', $member_user_id);
$stmt->bindValue(':temp_password', $random_password);
$stmt->bindValue(':expiry_date', 'now() + INTERVAL 3 DAY');
$insertResult = $stmt->execute();
I’ve also tried this:
$stmt->bindValue(':expiry_date', 'DATE_ADD(now(), INTERVAL 3 DAY)');
Alternate method proposed in several SO postings
Several SO postings (including this link) suggested putting the now() statement in the VALUES instead of binding it, but that causes an error message ‘Invalid parameter number: number of bound variables does not match number of tokens’
$stmt = $conn->prepare('INSERT INTO password_reset (user_id, temp_password, expiry_date)
VALUES(:user_id, :temp_password, :now() + INTERVAL 3 DAY)');
$stmt->bindValue(':user_id', $member_user_id);
$stmt->bindValue(':temp_password', $random_password);
$insertResult = $stmt->execute();
Remove the colon from
:now() + INTERVAL 3 DAY.Alternatively, you could do this:
When working with Prepared Statements, you should think of the statement as being a template to plug data into.
If you have a database table with the structure:
You have three columns in your table. Two of the values to insert into these columns will come from PHP, and the other will be evaluated by SQL. Since SQL will be doing all the work on the expiry_date column, it doesn’t need to be bound to anything in PHP.
So, examining the
INSERTstatement:Each parameter of the
VALUES()clause needs to match up to a declared column name in theINSERT INTO table (columns...)clause.In prepared statements, since we are creating a template, we use
placeholdersto show where we will be inserting values into the statement as it is executed. Placeholders can be either the:nameversion that you have used, or simply a question mark?.PDO::prepare($statement)tells the SQL server to prepare the statement. At that point, SQL has the template for your query, and is ready to receive the values for the placeholders in that query.PDOStatement::execute($placeholderValues)executes a single instance of that prepared statement, substituting the placeholders with the values you have either bound withbindParam,bindValue, or passed as the argument toexecute().So, basically, all that is being sent to the SQL server on each
execute()are the values to plug into the placeholders, instead of an entire query string.Now comes the part that explains why you weren’t able to
bindValue(":expiry_date", "now() + INTERVAL 3 DAY").When the values get to the SQL server, SQL server sanitizes them and replaces the respective placeholder with their value.
When you bind
"now() + INTERVAL 3 DAY", you are actually binding a string. Since it is a string, it doesn’t get executed as SQL code.