Vincent Musk
Vincent Musk

Reputation: 548

Understand PDO::ATTR_EMULATE_PREPARES = false completly

What I already know about PDO :: ATTR_EMULATE_PREPARES = false:

  1. You can bind on your own
  2. If you do not bind, the parameter is automatically set back to PDO :: ATTR_EMULATE_PREPARES = true
  3. PDO :: ATTR_EMULATE_PREPARES = false is a bit more secure
  4. You should pay attention to whether you get false from the request with PDO :: ATTR_EMULATE_PREPARES = false

So now my question, how do I look if false comes back and how do I deal with it and do I have to work with bind or is it enough to do Prepair and Execute?

Here is my code, please also check whether it is correct by then.

<?php

$options= [
    PDO::ATTR_EMULATE_PREPARES   => false,
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];

$db = new PDO('mysql:host=localhost;dbnam=db;charset=utf8', user, password, $options);

$stmt = $db->prepare("
    SELECT CURRENT_DATE AS ? FROM DUAL
    UNION ALL
    SELECT CURRENT_DATE FROM DUAL");

$stmt->bindParam(1, $date, PDO::PARAM_STR);

$stmt->execute(); // Do I now have to check if the result is false?

Upvotes: 0

Views: 2130

Answers (1)

mario
mario

Reputation: 145482

  1. You can bind on your own

EMULATE_PREPARES applies to both →bindParam and →execute likewise.

  1. If you do not bind, the parameter is automatically set back to PDO :: ATTR_EMULATE_PREPARES = true

No. The PDO setting has no influence on manually interpolated tidbits. If that's what "not bind" was supposed to mean.

If EMULATE_PREPARES was enabled, it applied to any bound parameter. Per default it typecasts any input to strings, escapes it, and interpolates it as '$escaped_str' in place of the placeholder.

The difference is that execute() interprets all parameters as strings per default, whereas bindParam can typecast and interpolate integers/floats as literals.

I have a feeling this question is based on the assumption that more long-winded code improves security. It doesn't. The only reason to use →bindParam in either case is to work around the lack of typecasting on some MySQL query contexts (such as the LIMIT clause). (Albeit LIMIT 1*?, 1*? is often the better workaround there.)

  1. PDO :: ATTR_EMULATE_PREPARES = false is a bit more secure

Sure.

  1. You should pay attention to whether you get false from the request with PDO :: ATTR_EMULATE_PREPARES = false

Not gonna happen in reality. The support for emulation is driver-dependent. It's not going to change at runtime for the same database driver and database server.

And you can't really check it, since EMULATE_PREPARES is a initialization option, not something that you usually adapt per PDO::setAttribute in between queries.

Ok so: $stmt = $pdo->prepare("SELECT id, max_bench, max_squat FROM myTable WHERE weight < ?"); $stmt->execute([$int]); AND $stmt = $pdo->prepare("SELECT id, max_bench, max_squat FROM myTable WHERE weight < ?"); $stmt->bindParam(1, $int, PDO::PARAM_INT); $stmt->execute(); does the same with PDO :: ATTR_EMULATE_PREPARES = false and also is same secure?

It's mostly the same, if $int was an integer already. bindParam() only does a secondary typecast, if need be. Irrelevant since MySQL would do the same on its end anyway, depending on the target columns type.

Upvotes: 2

Related Questions