Skip to content

PDOStatement can return objects but phpstan thinks its an array #9120

Closed

Description

@MacGritsch

Enumerating a PDOStatement can return objects but phpstan thinks its an array.
Snippet: https://phpstan.org/r/549677e4-9fde-4788-bb92-7a6e3f4c8fbc

Otherwise: thank you for the great work!

Activity

  1. zorac commented on Apr 12, 2023

    @zorac

    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.)

    - * @implements Traversable<array<int|string, mixed>>
    - * @implements IteratorAggregate<array<int|string, mixed>>
    + * @implements Traversable<mixed>
    + * @implements IteratorAggregate<mixed>
  2. AllenJB commented on Feb 25, 2025

    @AllenJB
    Sponsor

    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

  3. staabm commented on Feb 25, 2025

    @staabm
    Contributor

    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

  4. AllenJB commented on Feb 25, 2025

    @AllenJB
    Sponsor

    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)

  5. AllenJB commented on Mar 2, 2025

    @AllenJB
    Sponsor

    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

  6. AllenJB commented on Mar 5, 2025

    @AllenJB
    Sponsor

    I have updated the above mentioned test repo for the latest versions of phpstan and phpstan-dba

  7. phpstan-bot commented on Aug 30, 2025

    @phpstan-bot
    Contributor

    @MacGritsch After the latest push in 2.1.x, PHPStan now reports different result with your code snippet:

    @@ @@
    +PHP 8.0 – 8.2 (1 error)
    +==========
    +
    +14: Cannot access property $mycolumn on mixed.
    +
    +PHP 7.2 – 7.4 (1 error)
    +==========
    +
     14: Cannot access property $mycolumn on array<int|string, mixed>.
    Full report

    PHP 8.0 – 8.2 (1 error)

    Line Error
    14 Cannot access property $mycolumn on mixed.

    PHP 7.2 – 7.4 (1 error)

    Line Error
    14 `Cannot access property $mycolumn on array<int
  8. phpstan-bot commented on Aug 30, 2025

    @phpstan-bot
    Contributor

    @zorac After the latest push in 2.1.x, PHPStan now reports different result with your code snippet:

    @@ @@
    +PHP 8.0 – 8.2 (1 error)
    +==========
    +
    +14: Access to an undefined property object::$mycolumn.
    +
    +PHP 7.2 – 7.4 (1 error)
    +==========
    +
     10: PHPDoc tag @var contains unresolvable type.
    Full report

    PHP 8.0 – 8.2 (1 error)

    Line Error
    14 Access to an undefined property object::$mycolumn.

    PHP 7.2 – 7.4 (1 error)

    Line Error
    10 PHPDoc tag @var contains unresolvable type.
  9. phpstan-bot commented on Mar 6, 2026

    @phpstan-bot
    Contributor

    Closed via merging phpstan/phpstan-src#5132

  10. github-actions commented on Apr 7, 2026

    @github-actions

    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.

  11. locked as resolved and limited conversation to collaborators on Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions