You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PDOStatement can return objects but phpstan thinks its an array #9120
This may simply be a case of PHPStan not knowing the fetch mode and therefore the iterable type of the statement (as per #3271 this has a default which works for FETCH_ASSOC/FETCH_NUM/FETCH_BOTH)
The workaround (as suggested in #3509) should be to explicitly type the statement as \PDOStatement<object> or similar, but this now generates a different error: PHPDoc tag @var contains unresolvable type. (see https://phpstan.org/r/bddfabcb-164f-48e7-bf2e-b8f67939f655) Variants such as \PDOStatement<int,\stdClass> give the same error.
Note that explicit typing for array return types (e.g. \PDOStatement<int,array<string,mixed>> for FETCH_ASSOC) works correctly.
Looks like there's some sort of conflict with PDOStatement.stub and not being to override the iterable types set in there. If I change that file as per below then PHPStan works correctly with the example above (but presumably loses the default typing for array-return fetch modes and would throw up errors for people relying on that.)
Overriding the PDOStatement stub currently no longer works (without an unignorable error) due to stub validation. Related: #10906
The staabm/phpstan-dba extension can provide improvement in some circumstances (specifically I believe it only covers cases where the PDOStatement is immediately used in the same function/method as the query is run - see staabm/phpstan-dba#323 ), but requires additional setup (either an active DB connection or cached replays).
One solution would be to provide a configurable default fetch mode (and take into account passed fetch mode for methods that accept it as a parameter), similar to phpstan-dba
I do have phpstan-dba configured on this project, and have set the default fetch mode to QueryReflector::FETCH_TYPE_CLASS (which I believe should be the equivalent of PDO::FETCH_MODE_OBJECT), but am still seeing numerous reports of Cannot access property $code on array<int|string, mixed> (property.nonObject)
As I mentioned above I thought this was due to limitations in the way the phpstan-dba implementation works, but if that's not expected, I will look at reproduction cases.
I'll mention here that in some cases (specifically views) PHPStan is 100% relying on PHPDoc (which in some cases will just be @var PDOStatement $whatever) at the top of the file so has no idea what query produced the PDOStatement.
This project largely uses CodeIgniter 2 for controllers & views, and as far as I know there's no way to link the view file to the load->view() call to make PHPStan aware of what values were passed to the view. Note that it does not uses CI's models/db handling for DB models/repositories - those are directly loaded classes, using Aura.Sql's ExtendedPDO which has been additionally extended for some custom functionality such as more precise exceptions in specific circumstances.
Regardless, it would be nice if PHPStan itself was fetch mode aware, and there may be some cases where users cannot or do not want to run active DB connections / perform the additional setup phpstan-dba requires.
My personal current aim/desire is to get back to what I had with the PDOStatement stub override (changing the Traversable/IteratorAggregate subtypes to object) before I upgraded to PHPStan 2.0 (without the unignoreable "class declared multiple times" error, which as far as I know I can't get GitHub Actions to ignore, at least without doing something crazy like piping PHPStans output and return code through another script)
I've annotated the tests/data files with the failures, and they're also available in the phpunit report .xml in the repo root.
As expected, even with PHPStan DBA configured with default fetch mode, anything "at a distance" is still interpreted as using an array-based fetch mode.
Activity
zorac commentedon Apr 12, 2023
This may simply be a case of PHPStan not knowing the fetch mode and therefore the iterable type of the statement (as per #3271 this has a default which works for
FETCH_ASSOC/FETCH_NUM/FETCH_BOTH)The workaround (as suggested in #3509) should be to explicitly type the statement as
\PDOStatement<object>or similar, but this now generates a different error:PHPDoc tag @var contains unresolvable type.(see https://phpstan.org/r/bddfabcb-164f-48e7-bf2e-b8f67939f655) Variants such as\PDOStatement<int,\stdClass>give the same error.Note that explicit typing for array return types (e.g.
\PDOStatement<int,array<string,mixed>>forFETCH_ASSOC) works correctly.Looks like there's some sort of conflict with
PDOStatement.stuband not being to override the iterable types set in there. If I change that file as per below then PHPStan works correctly with the example above (but presumably loses the default typing for array-return fetch modes and would throw up errors for people relying on that.)AllenJB commentedon Feb 25, 2025
Overriding the PDOStatement stub currently no longer works (without an unignorable error) due to stub validation. Related: #10906
The staabm/phpstan-dba extension can provide improvement in some circumstances (specifically I believe it only covers cases where the PDOStatement is immediately used in the same function/method as the query is run - see staabm/phpstan-dba#323 ), but requires additional setup (either an active DB connection or cached replays).
See also staabm/phpstan-dba#269
One solution would be to provide a configurable default fetch mode (and take into account passed fetch mode for methods that accept it as a parameter), similar to phpstan-dba
staabm commentedon Feb 25, 2025
phpstan-dba supports a default fetch mode RuntimeConfiguration for PDO
https://github.com/staabm/phpstan-dba/blob/main/docs/configuration.md
If you have repro cases at hand in which phpstan-dba can be improved, feel free to open a issue
AllenJB commentedon Feb 25, 2025
I do have phpstan-dba configured on this project, and have set the default fetch mode to
QueryReflector::FETCH_TYPE_CLASS(which I believe should be the equivalent ofPDO::FETCH_MODE_OBJECT), but am still seeing numerous reports ofCannot access property $code on array<int|string, mixed>(property.nonObject)As I mentioned above I thought this was due to limitations in the way the phpstan-dba implementation works, but if that's not expected, I will look at reproduction cases.
I'll mention here that in some cases (specifically views) PHPStan is 100% relying on PHPDoc (which in some cases will just be
@var PDOStatement $whatever) at the top of the file so has no idea what query produced the PDOStatement.This project largely uses CodeIgniter 2 for controllers & views, and as far as I know there's no way to link the view file to the load->view() call to make PHPStan aware of what values were passed to the view. Note that it does not uses CI's models/db handling for DB models/repositories - those are directly loaded classes, using Aura.Sql's ExtendedPDO which has been additionally extended for some custom functionality such as more precise exceptions in specific circumstances.
Regardless, it would be nice if PHPStan itself was fetch mode aware, and there may be some cases where users cannot or do not want to run active DB connections / perform the additional setup phpstan-dba requires.
My personal current aim/desire is to get back to what I had with the PDOStatement stub override (changing the Traversable/IteratorAggregate subtypes to object) before I upgraded to PHPStan 2.0 (without the unignoreable "class declared multiple times" error, which as far as I know I can't get GitHub Actions to ignore, at least without doing something crazy like piping PHPStans output and return code through another script)
AllenJB commentedon Mar 2, 2025
I've created a minimal reproduction / test repo: https://github.com/AllenJB/phpstan-pdo-tests
I've annotated the tests/data files with the failures, and they're also available in the phpunit report .xml in the repo root.
As expected, even with PHPStan DBA configured with default fetch mode, anything "at a distance" is still interpreted as using an array-based fetch mode.
(I also found another issue with PHPStan DBA's types here: staabm/phpstan-dba#748 )
Edit: Related discussion on developing a fix/solution for this: #12670
AllenJB commentedon Mar 5, 2025
I have updated the above mentioned test repo for the latest versions of phpstan and phpstan-dba
phpstan-bot commentedon Aug 30, 2025
@MacGritsch After the latest push in 2.1.x, PHPStan now reports different result with your code snippet:
Full report
PHP 8.0 – 8.2 (1 error)
Cannot access property $mycolumn on mixed.PHP 7.2 – 7.4 (1 error)
phpstan-bot commentedon Aug 30, 2025
@zorac After the latest push in 2.1.x, PHPStan now reports different result with your code snippet:
Full report
PHP 8.0 – 8.2 (1 error)
Access to an undefined property object::$mycolumn.PHP 7.2 – 7.4 (1 error)
PHPDoc tag @var contains unresolvable type.phpstan-bot commentedon Mar 6, 2026
Closed via merging phpstan/phpstan-src#5132
github-actions commentedon Apr 7, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.