php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75130 array_filter pass-by-ref broken
Submitted: 2017-08-28 12:11 UTC Modified: 2017-08-28 18:29 UTC
From: kernins at gmail dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 7.1.8 OS: Linux x86_64
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kernins at gmail dot com
New email:
PHP Version: OS:

 

 [2017-08-28 12:11 UTC] kernins at gmail dot com
Description:
------------
Passing array element to callback by ref doesn't work anymore, resulting array contains original/unmodified values

Test script:
---------------
$arr=['foo', 'bar', '', 'baz'];

$arr=array_filter($arr, function(&$el){
	$el=strtoupper($el);
	return strlen($el)>0;
});
var_dump($arr);

Expected result:
----------------
array(3) {
  [0]=>
  string(3) "FOO"
  [1]=>
  string(3) "BAR"
  [3]=>
  string(3) "BAZ"
}

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


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-08-28 12:27 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2017-08-28 12:27 UTC] nikic@php.net
If a function doesn't explicitly document that it's operating on references (such as array_walk), then you can generally assume that it does not work with references.

The correct way to write this code is a combination of array_map and array_filter.
 [2017-08-28 13:49 UTC] kernins at gmail dot com
First of all, it worked the whole 5.x series and I have a lot of code using it that way. Such usage was considered valid before => BC break here.

2nd
>The correct way to write this code is a combination of array_map and array_filter.

This will result in two loops instead of one => performance hit on large arrays (even if it is negligible, it is still here) and less compact code.

3rd
Why the hell one array_* functions are working with refs, while the others shouldn't? This at least adds even more inconsistency to already inconsistent php api.

So, this IS a bug
 [2017-08-28 13:51 UTC] spam2 at rhsoft dot net
http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html
 [2017-08-28 14:05 UTC] nikic@php.net
> First of all, it worked the whole 5.x series and I have a lot of code using it that way. Such usage was considered valid before => BC break here.

Sure. It's a BC break in a semver-major release fixing a bug in the previous implementation.

> This will result in two loops instead of one => performance hit on large arrays (even if it is negligible, it is still here) and less compact code.

If you are interested in performance, using array_filter() and similar is already a losing proposition. The most efficient way to perform any kind of loop-based operation is a foreach() loop.

People use functions like array_map() or array_filter() not for reasons of performance, but for reasons of clarity. It goes without saying that the ability to perform modifications inside a function called "filter", which is a very well-defined functional programming construct that certainly does not include mutability, somewhat defeats the purpose of having a well-delineated functional processing pipeline.

    $arr = array_map('strtoupper', array_filter($arr, 'strlen'));

> Why the hell one array_* functions are working with refs, while the others shouldn't? This at least adds even more inconsistency to already inconsistent php api.

Because some functions operate in-place, while others return new arrays. Functions operating in-place (array_walk, sort, shuffle) accept by-reference, while nearly all other functions (array_map, array_filter) do not operate in-place and accept by-value.
 [2017-08-28 18:29 UTC] kernins at gmail dot com
>the ability to perform modifications inside a function called "filter", which is a very well-defined functional programming construct that certainly does not include mutability, somewhat defeats the purpose of having a well-delineated functional processing pipeline

Well, that makes perfect sense. Agreed
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Jul 05 04:01:35 2025 UTC