19

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?

Ollie Saunders
  • 7,787
  • 3
  • 29
  • 37
Chris
  • 8,736
  • 18
  • 49
  • 56

6 Answers6

61

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
));
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
Stefan Gehrig
  • 82,642
  • 24
  • 155
  • 189
  • 1
    How would you get around a mismatched number of bound variables and tokens? When I tried this I got an error message 'Invalid parameter number: number of bound variables does not match number of tokens'. I know this is an old posting, but it's the best answer that I've found so far :-) – Chaya Cooper Jan 29 '13 at 16:01
17

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);
Kenneth Vogt
  • 985
  • 4
  • 12
  • 28
  • 7
    this assumes your app server running PHP is in the same timezone as your DB servers no? – Angel S. Moreno Jul 22 '16 at 15:56
  • 2
    Speaking from experience, using `date` and `strtotime` functions for reading and writing to the database is a bad idea. They indeed utilize the PHP timezone setting and could change your timestamp before it gets to the database. You probably wont notice it unless you look at the value in the database (e.g. with workbench). To avoid headaches, i suggest letting the database handle the setting of NOW() and set the database connection timezone and server timezone to UTC. Application code should then do any timezone conversions from UTC when reading the value. – Phil Sep 23 '16 at 09:08
  • @Angel S. Moreno: It assumes no such thing. Does his 'time_created' refer to the creation of the database, or to the creation of the record in question? The latter, I propose, and if that is so, philosophically/practically the 'time_created' refers to a time 'closest' to the user and his record-editing-event; in this sense, closest would be determined by the distance between him and the server, which he cannot make any assumptions about. But to presume that it should be the database's time is, at least in this example, incorrect. –  Jan 04 '17 at 03:02
  • 1
    You misunderstood me. If you ask PHP for the time, it will use the timezone in the php.ini and if you ask MySQL for the time, it will use the mysql.cnf file. If these timezones are not the same, you will get the wrong dates. In the 18 years I've been working on *nix servers, I've had to address this on a few dozen occasions because the timezones were different. – Angel S. Moreno Jan 04 '17 at 04:08
7

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... :-}

Elmo
  • 6,409
  • 16
  • 72
  • 140
B.F.U.
  • 71
  • 1
  • 1
4

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.

Andy Obusek
  • 12,614
  • 4
  • 41
  • 62
2

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())
Andrew Klaassen
  • 206
  • 1
  • 8
1

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.

Sabeen Malik
  • 10,816
  • 4
  • 33
  • 50