php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74038 Arrays unchanged when value reference is modified in an array_filter(), etc
Submitted: 2017-02-03 01:51 UTC Modified: 2017-02-03 06:52 UTC
From: Rican7 at gmail dot com Assigned:
Status: Duplicate Package: Arrays related
PHP Version: 7.0.15 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: Rican7 at gmail dot com
New email:
PHP Version: OS:

 

 [2017-02-03 01:51 UTC] Rican7 at gmail dot com
Description:
------------
I just updated an application from PHP 5.6 to PHP 7.0 after carefully reading the upgrading guide and documentation, but I just ran into a bit of an issue.

We had code that was modifying values (via a value reference) in place when passed to an `array_filter()` call, to prevent us from having to run multiple loop iterations, but that doesn't seem to work in PHP 7.

While I understand that the runtime semantics may have changed for these functions, I can't find this behavior change to be documented anywhere, so I wasn't sure if it was intentional or not. I know that `foreach` has changed in PHP 7, which is relatively well documented, but these array function behavior changes don't seem to be.

I've tried to see if this behavior has changed in other array functions too, such as `array_reduce`, and the issue seems to exist there too. My guess is that this has to do with how values are passed/referenced in these functions under the new PHP 7 runtime/engine.

Test script:
---------------
/**
 * 3v4l.org URL: https://3v4l.org/bERrp
 */

$data = ['foo', 'bar'];

var_dump($data);

$filtered = array_filter($data, function (&$value) {
    $value = (bool) $value;
    
    return true;
});

var_dump($filtered);

Expected result:
----------------
array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
}
array(2) {
  [0]=>
  bool(true)
  [1]=>
  bool(true)
}

Actual result:
--------------
array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
}
array(2) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-02-03 02:24 UTC] Rican7 at gmail dot com
Ah, this seems to be related to (if not the same issue as) #71240: https://bugs.php.net/bug.php?id=71240
 [2017-02-03 05:30 UTC] requinix@php.net
-Status: Open +Status: Duplicate
 [2017-02-03 05:30 UTC] requinix@php.net
Yeah, same basic issue. Those functions never claimed you could modify the values inside the callbacks, so the fact that you could in PHP 5 was a quirk.
 [2017-02-03 06:16 UTC] Rican7 at gmail dot com
Ah, so taking a value by reference in the callback is really just "undefined" behavior that shouldn't be relied on anyway?
 [2017-02-03 06:52 UTC] requinix@php.net
No, references in general are well defined. Functions that say they support references do, functions that don't say they support references don't (probably).

Imagine you were writing array_filter() using PHP code: references might work in one version (https://3v4l.org/YDZXk) but then you revise the code and now references don't work (https://3v4l.org/7OgqC).
array_filter_() never claimed it worked with references. There's no documentation to suggest it does. But for a while it did. Then the implementation changed and now it doesn't.

It's not so much a matter of references working before but rather you being able to get away with it.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Jul 25 16:01:28 2024 UTC