Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion resources/functionMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -7833,7 +7833,10 @@
'PDOStatement::errorInfo' => ['array'],
'PDOStatement::execute' => ['bool', 'bound_input_params='=>'?array'],
'PDOStatement::fetch' => ['mixed', 'how='=>'int', 'orientation='=>'int', 'offset='=>'int'],
'PDOStatement::fetchAll' => ['array|false', 'how='=>'int', 'fetch_argument='=>'int|string|callable', 'ctor_args='=>'?array'],
'PDOStatement::fetchAll' => ['array|false', 'how='=>'int'],
'PDOStatement::fetchAll\'1' => ['array|false', 'fetch_column'=>'int', 'colno'=>'int'],
'PDOStatement::fetchAll\'2' => ['array|false', 'fetch_class'=>'int', 'classname'=>'string', 'ctorargs='=>'?array'],
'PDOStatement::fetchAll\'3' => ['array|false', 'fetch_func'=>'int', 'callback'=>'callable'],
'PDOStatement::fetchColumn' => ['string|null|false|int', 'column_number='=>'int'],
'PDOStatement::fetchObject' => ['mixed', 'class_name='=>'string', 'ctor_args='=>'?array'],
'PDOStatement::getAttribute' => ['mixed', 'attribute'=>'int'],
Expand Down
5 changes: 4 additions & 1 deletion resources/functionMap_php80delta.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@
'opcache_get_configuration' => ['array{directives: array{\'opcache.enable\': bool, \'opcache.enable_cli\': bool, \'opcache.use_cwd\': bool, \'opcache.validate_timestamps\': bool, \'opcache.validate_permission\': bool, \'opcache.validate_root\'?: bool, \'opcache.dups_fix\': bool, \'opcache.revalidate_path\': bool, \'opcache.log_verbosity_level\': int, \'opcache.memory_consumption\': int, \'opcache.interned_strings_buffer\': int, \'opcache.max_accelerated_files\': int, \'opcache.max_wasted_percentage\': float, \'opcache.consistency_checks\': int, \'opcache.force_restart_timeout\': int, \'opcache.revalidate_freq\': int, \'opcache.preferred_memory_model\': string, \'opcache.blacklist_filename\': string, \'opcache.max_file_size\': int, \'opcache.error_log\': string, \'opcache.protect_memory\': bool, \'opcache.save_comments\': bool, \'opcache.record_warnings\': bool, \'opcache.enable_file_override\': bool, \'opcache.optimization_level\': int, \'opcache.lockfile_path\'?: string, \'opcache.mmap_base\'?: string, \'opcache.file_cache\': string, \'opcache.file_cache_only\': bool, \'opcache.file_cache_consistency_checks\': bool, \'opcache.file_cache_fallback\'?: bool, \'opcache.file_update_protection\': int, \'opcache.opt_debug_level\': int, \'opcache.restrict_api\': string, \'opcache.huge_code_pages\'?: bool, \'opcache.preload\': string, \'opcache.preload_user\'?: string, \'opcache.cache_id\'?: string, \'opcache.jit\'?: string, \'opcache.jit_buffer_size\'?: int, \'opcache.jit_debug\'?: int, \'opcache.jit_bisect_limit\'?: int, \'opcache.jit_blacklist_root_trace\'?: int, \'opcache.jit_blacklist_side_trace\'?: int, \'opcache.jit_hot_func\'?: int, \'opcache.jit_hot_loop\'?: int, \'opcache.jit_hot_return\'?: int, \'opcache.jit_hot_side_exit\'?: int, \'opcache.jit_max_exit_counters\'?: int, \'opcache.jit_max_loop_unrolls\'?: int, \'opcache.jit_max_polymorphic_calls\'?: int, \'opcache.jit_max_recursive_calls\'?: int, \'opcache.jit_max_recursive_returns\'?: int, \'opcache.jit_max_root_traces\'?: int, \'opcache.jit_max_side_traces\'?: int, \'opcache.jit_prof_threshold\'?: int}, version: array{version: non-empty-string, opcache_product_name: non-empty-string}, blacklist: list<string>}|false'],
'parse_str' => ['void', 'encoded_string'=>'string', '&w_result'=>'array'],
'password_hash' => ['non-empty-string', 'password'=>'string', 'algo'=>'string|int|null', 'options='=>'array'],
'PDOStatement::fetchAll' => ['array', 'how='=>'int', 'fetch_argument='=>'int|string|callable', 'ctor_args='=>'?array'],
'PDOStatement::fetchAll' => ['array', 'mode='=>'int'],
'PDOStatement::fetchAll\'1' => ['array', 'mode'=>'int', 'column'=>'int'],
'PDOStatement::fetchAll\'2' => ['array', 'mode'=>'int', 'class'=>'string', 'constructorArgs='=>'?array'],
'PDOStatement::fetchAll\'3' => ['array', 'mode'=>'int', 'callback'=>'callable'],
'PhpToken::tokenize' => ['list<PhpToken>', 'code'=>'string', 'flags='=>'int'],
'PhpToken::is' => ['bool', 'kind'=>'string|int|string[]|int[]'],
'PhpToken::isIgnorable' => ['bool'],
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4062,6 +4062,16 @@ public function testBug14549(): void
]);
}

#[RequiresPhp('>= 8.0.0')]
public function testBug5509(): void
{
$this->checkThisOnly = false;
$this->checkNullables = true;
$this->checkUnionTypes = true;
$this->checkExplicitMixed = true;
$this->analyse([__DIR__ . '/data/bug-5509.php'], []);
}

public function testBug11894(): void
{
$this->checkThisOnly = false;
Expand Down
29 changes: 29 additions & 0 deletions tests/PHPStan/Rules/Methods/data/bug-5509.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php // lint >= 8.0

namespace Bug5509;

class Foo
{
public function test(\PDOStatement $stmt): void

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.

in the docs on https://www.php.net/manual/en/class.pdostatement.php

I can see

grafik

can we make more tests out of that?

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 tests for PDOStatement implementing IteratorAggregate and Traversable as the reviewer requested:

  • foreach iteration over PDOStatement
  • Calling getIterator() on PDOStatement
  • Passing PDOStatement to Traversable and IteratorAggregate typehints

All tests pass (12044 tests, 79632 assertions) and make phpstan reports no errors.

{
// FETCH_CLASS with class name and constructor args - should not error
$stmt->fetchAll(\PDO::FETCH_CLASS, \stdClass::class, [new \stdClass]);

// FETCH_CLASS with just class name - should not error
$stmt->fetchAll(\PDO::FETCH_CLASS, \stdClass::class);

// FETCH_COLUMN with column number - should not error
$stmt->fetchAll(\PDO::FETCH_COLUMN, 0);

// FETCH_FUNC with callable - should not error
$stmt->fetchAll(\PDO::FETCH_FUNC, function () {
return 'test';
});

// No args - should not error
$stmt->fetchAll();

// With just mode - should not error
$stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
Loading