Skip to content

ForEach does not issue an error for non-iterable non-Traversable objects #4534

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
divinity76 opened this issue Mar 13, 2025 · 3 comments · May be fixed by #4535
Open

ForEach does not issue an error for non-iterable non-Traversable objects #4534

divinity76 opened this issue Mar 13, 2025 · 3 comments · May be fixed by #4535
Labels
bug Documentation contains incorrect information Status: Needs Triage

Comments

@divinity76
Copy link
Contributor

divinity76 commented Mar 13, 2025

Description

The following code:

<?php
declare(strict_types=1);
error_reporting(E_ALL);
\set_error_handler(function ($errno, $errstr, $errfile, $errline) {
    if (\error_reporting() & $errno) {
        throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
    }
});
$a = ["foo" => "bar"];
$o = (object)$a;
$isIterable = is_iterable($o); // false
$isTraversable = $o instanceof Traversable; // false
var_dump(["isIterable" => $isIterable, "isTraversable" => $isTraversable]);
/*
Quoting https://www.php.net/manual/en/control-structures.foreach.php
The foreach construct provides an easy way to iterate over arrays and Traversable objects.
>>>foreach will issue an error when used with a variable containing a different data type<<<
*/
foreach ($o as $key => $val) {
    var_dump(["key" => $key, "val" => $val]);
}
?>

Resulted in this output:

array(2) {
  ["isIterable"]=>
  bool(false)
  ["isTraversable"]=>
  bool(false)
}
array(2) {
  ["key"]=>
  string(3) "foo"
  ["val"]=>
  string(3) "bar"
}

But given the ForEach documentation, I expected this output instead:

array(2) {
  ["isIterable"]=>
  bool(false)
  ["isTraversable"]=>
  bool(false)
}
Fatal error: Uncaught TypeError: ForEach: Argument php/php-src#1 (iterable_expression) must be iterable or instance of Traversable

(some variant of that)

So it seems either the documentation or the implementation is wrong here.

PHP Version

PHP 8.4.5

Operating System

Ubuntu24.04

@divinity76 divinity76 added bug Documentation contains incorrect information Status: Needs Triage labels Mar 13, 2025
@divinity76
Copy link
Contributor Author

divinity76 commented Mar 13, 2025

Notably, if the implementation is changed to match the documentation, it would break a lot of code in the wild..

(unless we make all objects implement traversable by default, that would be a BC-compatible way of fixing it, but that would make the traversable interface pointless, I think)

@iluuu1994
Copy link
Member

iluuu1994 commented Mar 13, 2025

All objects are iterable by default (not in the iterator api sense, but in that foreach accepts them). This is legacy behavior and cannot easily be removed. The documentation could be clearer though. Moving this to the appropriate repository.

@iluuu1994 iluuu1994 transferred this issue from php/php-src Mar 13, 2025
@divinity76
Copy link
Contributor Author

divinity76 commented Mar 13, 2025

it's not just unclear, it's wrong. if it changed to

The foreach construct provides an easy way to iterate over arrays and objects.

it would be correct. or

foreach will issue an error when used with a variable containing a different data type (except for objects)

would also be correct.
but the current wording

The foreach construct provides an easy way to iterate over arrays and Traversable objects. foreach will issue an error when used with a variable containing a different data type

is wrong.

divinity76 added a commit to divinity76/doc-en that referenced this issue Mar 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Documentation contains incorrect information Status: Needs Triage
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants