MySQL/PDO::quote(), Putting single quotes around i

2019-06-28 09:19发布

问题:

It appears no matter what value/data-type pair I pass to $pdo->quote($value, $type);, it always quotes it as a string:

echo $pdo->quote('foo', PDO::PARAM_STR); /* 'foo', as expected */

echo $pdo->quote(42, PDO::PARAM_INT);    /* '42', expected 42 unquoted */

I'm just curious to know if this is the intended functionality. I use prepared statements for actual query execution, but I'm trying to fetch create the final querystrings (for debugging/caching), and am constructing them manually.

As the title suggests, this is when $pdo is created using the MySQL driver. I haven't tried others due to unavailability.

回答1:

The Oracle, SQLite, MSSQL, and Firebird drivers all quote as the PDO MySQL driver, ignoring the param type. The PostgreSQL driver only distinguishes between binary large objects and all others. ODBC Driver doesn't implement a quoter. The (lack of) behavior you expect was reported as a bug and closed as "bogus", meaning the behavior is by design. Perhaps the documentation is misleading when it states:

PDO::quote() places quotes around the input string (if required)

While this suggests there may be instances when values aren't surrounded by quotes, it doesn't say there definitely are, nor does it state what those instances are. If you feel this is a bug in documentation, submit a bug report, preferably with a fix.



回答2:

  public static function quote($value, $pdotype = PDO::PARAM_STR)
    {
        if ($pdotype == PDO::PARAM_INT)
            return (int)$value;
        return Db::pdo()->quote($value, $pdotype);
    }

According to the PDO developers it's a intentional error in their code and in their documentation.
They do not seem to plan to correct it, so you can do it yourself by wrapping their errornous function and replacing the behaviour as needed.
You actually have no choice as in some cases you NEED a correct quote behaviour for numbers, you can't just use string quoting everywhere as SQL might just not take it.

As a sidenote, the above function will make a 0 out of any illegal data.
SQL injections are not possible but it will not throw an error. If you want to catch errors you could do a "strlen" on both variables and if that differs you know there was a problem or an intrusion attempt.