From 23c4b10c4a6736ca2f8f4881983ad25be1c0be7e Mon Sep 17 00:00:00 2001 From: "Etienne V. Labelle" Date: Sun, 12 Apr 2026 11:20:46 -0400 Subject: [PATCH 1/2] test: add failing tests for PDOStatement subclass execute() check --- tests/default/Fixture/MyPdoStatement.php | 13 +++++++++ .../PdoStatementExecuteMethodRuleTest.php | 18 +++++++++++++ .../data/pdo-stmt-execute-subclassed.php | 27 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/default/Fixture/MyPdoStatement.php create mode 100644 tests/rules/data/pdo-stmt-execute-subclassed.php diff --git a/tests/default/Fixture/MyPdoStatement.php b/tests/default/Fixture/MyPdoStatement.php new file mode 100644 index 00000000..43a599a1 --- /dev/null +++ b/tests/default/Fixture/MyPdoStatement.php @@ -0,0 +1,13 @@ +analyse([__DIR__ . '/data/pdo-stmt-execute-subclassed.php'], [ + [ + 'Query expects placeholder :adaid, but it is missing from values given.', + 14, + ], + [ + 'Value :wrongParamName is given, but the query does not contain this placeholder.', + 14, + ], + [ + 'Query expects placeholder :adaid, but it is missing from values given.', + 18, + ], + ]); + } } diff --git a/tests/rules/data/pdo-stmt-execute-subclassed.php b/tests/rules/data/pdo-stmt-execute-subclassed.php new file mode 100644 index 00000000..5c615b2f --- /dev/null +++ b/tests/rules/data/pdo-stmt-execute-subclassed.php @@ -0,0 +1,27 @@ +prepare('SELECT email, adaid FROM ada WHERE adaid = :adaid'); + assert($stmt instanceof MyPdoStatement); + $stmt->execute(['wrongParamName' => 1]); // error: wrong param name + + $stmt = $pdo->prepare('SELECT email, adaid FROM ada WHERE adaid = :adaid'); + assert($stmt instanceof MyPdoStatement); + $stmt->execute(); // error: missing parameter + } + + public function noErrors(PDO $pdo): void + { + $stmt = $pdo->prepare('SELECT email, adaid FROM ada WHERE adaid = :adaid'); + assert($stmt instanceof MyPdoStatement); + $stmt->execute(['adaid' => 1]); // correct + } +} From 011fa5611d1b9cbda68d222fa0acc438e91326e5 Mon Sep 17 00:00:00 2001 From: "Etienne V. Labelle" Date: Sun, 12 Apr 2026 11:21:22 -0400 Subject: [PATCH 2/2] fix: check var type instead of declaring class to support PDOStatement subclasses --- src/Rules/PdoStatementExecuteMethodRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rules/PdoStatementExecuteMethodRule.php b/src/Rules/PdoStatementExecuteMethodRule.php index 1917de2c..d57e7175 100644 --- a/src/Rules/PdoStatementExecuteMethodRule.php +++ b/src/Rules/PdoStatementExecuteMethodRule.php @@ -43,7 +43,7 @@ public function processNode(Node $methodCall, Scope $scope): array return []; } - if (PDOStatement::class !== $methodReflection->getDeclaringClass()->getName()) { + if (!(new \PHPStan\Type\ObjectType(PDOStatement::class))->isSuperTypeOf($scope->getType($methodCall->var))->yes()) { return []; }