问题
I have following piece of code (PHP 7.3.16) which retrieves some data from database (MySQL):
// db credentials
$dbhost = "localhost";
$dbuser = "user";
$dbpass = "password";
$dbname = "database";
// pdo
$dsn = "mysql:host=".$dbhost.";dbname=".$dbname.";charset=utf8";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];
$pdo = new PDO($dsn, $dbuser, $dbpass, $options);
// run sql query
$sql = "SELECT * FROM foo WHERE bar > ?";
$pdo_parameters = [ 1 ];
// this will produce no results without any error:
// $pdo_parameters = [ 1, 2, 3 ];
$stmt = $pdo->prepare($sql);
$stmt->execute( $pdo_parameters );
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
var_dump($row);
}
If array $pdo_parameters
contains only 1 element then everything works as expected and I receive a result. However when $pdo_parameters
contains more than one I don't receive any results at all without any exception message. PHP errors are active, but I don't see any PDO error message. Why?
I would like to raise an PHP exception if there are too many parameters. Is that possible?
Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number in /tmp/test:42 Stack trace: #0 /tmp/test.php(42): PDOStatement->execute(Array) #1 {main} thrown in /tmp/test.php on line 42
I have a huge code base and need in such cases a proper exception handling. However I don't understand why PHP doesn't raise an exception in that case. Is this just another PHP bug or if there is just no way for PHP (PHP C internals) to check if there are too many PDO parameters? I know how to check that by myself in plain PHP (could be pretty inaccurate though if we have "?" in some strings), but it would be better if PHP PDO extension would have a function to check such cases.
EDIT: It is a known PHP bug: https://bugs.php.net/bug.php?id=77490 (first report from 20 January 2019)
回答1:
You're right, that situation doesn't seem to throw exceptions nor trigger errors. PDOStatement::execute() at least returns false
so you can roll your own:
$dsn = "mysql:host=$dbhost;dbname=$dbname;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $dbuser, $dbpass, $options);
$sql = 'SELECT ? AS foo';
$stmt = $pdo->prepare($sql);
if (!$stmt->execute([1, 2])) {
throw new InvalidArgumentException('Failed to execute statement');
}
while ($row = $stmt->fetch()) {
var_dump($row);
}
Not ideal but...
回答2:
To check what param were provided use this: https://www.php.net/manual/en/pdostatement.debugdumpparams.php,
Also use param bindings to be absolutely sure that you have bind the params the right way:
https://www.php.net/manual/en/pdostatement.bindparam.php
来源:https://stackoverflow.com/questions/61617834/how-to-check-in-php-if-more-pdo-parameters-provided-than-needed