Skip to content

Return list<mixed> from PDOStatement::fetchAll() in function signature map#5643

Open
phpstan-bot wants to merge 4 commits into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-e4psdj6
Open

Return list<mixed> from PDOStatement::fetchAll() in function signature map#5643
phpstan-bot wants to merge 4 commits into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-e4psdj6

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

@phpstan-bot phpstan-bot commented May 11, 2026

…`, and `pg_fetch_all_columns()` in function signature map

- Change PDOStatement::fetchAll() return type from `array` to `list<mixed>` (PHP 8.0+) and from `array|false` to `list<mixed>|false` (pre-8.0) across all four overload variants
- Change pg_fetch_all() return type from `array<non-empty-list<string|null>>` to `list<non-empty-list<string|null>>`
- Change pg_fetch_all_columns() return type from `array|false` to `list<string|null>|false`
- Change sqlite_fetch_all() return type from `array` to `list<mixed>`
- All these functions return sequentially 0-indexed arrays, which are lists by definition
- mysqli_fetch_all / mysqli_result::fetch_all were already correctly typed as `list<array>`
Comment on lines +13 to +18
assertType('list<mixed>', $stmt->fetchAll());
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_ASSOC));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_COLUMN, 0));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_CLASS, \stdClass::class));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_CLASS, \stdClass::class, []));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_FUNC, function () {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FETCH_COLUMN, FETCH_ASSOC and PDO::FETCH_CLASS return a list. But not with PDO::FETCH_KEY_PAIR and FETCH_GROUP

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed. The change reverts the default PDOStatement::fetchAll() overload variant back to array (both in functionMap.php and functionMap_php80delta.php) since it covers modes like FETCH_KEY_PAIR and FETCH_GROUP that return associative arrays, not lists. The specific overload variants for FETCH_COLUMN, FETCH_CLASS, and FETCH_FUNC correctly remain list<mixed>. Tests and PHPStan self-analysis both pass clean.

The default overload variant covers all fetch modes including
FETCH_KEY_PAIR and FETCH_GROUP which return associative arrays,
not lists. Only the specific overload variants (FETCH_COLUMN,
FETCH_CLASS, FETCH_FUNC) are guaranteed to return lists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@staabm staabm requested a review from VincentLanglet May 12, 2026 05:46
Comment thread resources/functionMap.php Outdated
Comment on lines +7878 to +7879
'pg_fetch_all' => ['list<non-empty-list<string|null>>', 'result'=>'resource', 'result_type='=>'int'],
'pg_fetch_all_columns' => ['list<string|null>|false', 'result'=>'resource', 'column_number='=>'int'],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are wrong, revert them

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Reverted pg_fetch_all, pg_fetch_all_columns, and sqlite_fetch_all back to their original array return types as requested by the reviewer. Tests and PHPStan self-analysis both pass clean.

Comment thread resources/functionMap.php Outdated
'sqlite_exec' => ['bool', 'dbhandle'=>'', 'query'=>'string', 'error_msg='=>'string'],
'sqlite_factory' => ['SQLiteDatabase', 'filename'=>'string', 'mode='=>'int', 'error_message='=>'string'],
'sqlite_fetch_all' => ['array', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'],
'sqlite_fetch_all' => ['list<mixed>', 'result'=>'', 'result_type='=>'int', 'decode_binary='=>'bool'],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is not documented on php.net - I think we should not try to narrow its types

@staabm staabm changed the title Return list<mixed> from PDOStatement::fetchAll(), pg_fetch_all(), and pg_fetch_all_columns() in function signature map Return list<mixed> from PDOStatement::fetchAll() in function signature map May 12, 2026
…changes

These functions should not have their return types narrowed to list:
- pg_fetch_all/pg_fetch_all_columns: revert to original array types
- sqlite_fetch_all: undocumented on php.net, keep as array

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_COLUMN, 0));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_CLASS, \stdClass::class));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_CLASS, \stdClass::class, []));
assertType('list<mixed>', $stmt->fetchAll(PDO::FETCH_FUNC, function () {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert $stmt->fetchAll(\PDO::FETCH_GROUP | \PDO::FETCH_ASSOC); will not return a list

see https://www.php.net/manual/en/pdo.constants.fetch-modes.php#pdo.constants.fetch-group

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test assertion verifying that $stmt->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC) returns array (not list), as requested by staabm. This works correctly because the bitwise-OR'd mode still matches the default overload variant (single int argument), which returns array. Tests and PHPStan self-analysis both pass clean.

… list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants