php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #77321 array_filter combined with references
Submitted: 2018-12-20 09:06 UTC Modified: 2018-12-21 09:27 UTC
From: php at kingsquare dot nl Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 7.0.0 OS:
Private report: No CVE-ID: None
 [2018-12-20 09:06 UTC] php at kingsquare dot nl
Description:
------------
This is probably on purpose, but there is an undocumented backwards compatibility issue betwee PHP5 and PHP7. I know this might be a bit late to the party, but still.

It involves the differnce in using array_filter and references. 

Test script:
---------------
<?php
// also see https://3v4l.org/Z2HnL
$input = [1, 2];
var_dump(array_filter($input, function(& $value) {
    if ($value % 2 === 0) {
        return false;
    }
    $value++;
    return true;
}));

Expected result:
----------------
As the changelog doesn't seem to mention anything related to this I would expect them to be the same result [(int)2].

Actual result:
--------------
PHP5: [2]
PHP7: [1]


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-12-20 16:56 UTC] requinix@php.net
-Status: Open +Status: Not a bug -PHP Version: 7.3.0 +PHP Version: 7.0.0
 [2018-12-20 16:56 UTC] requinix@php.net
array_filter never supported by-ref values. The fact that it worked in PHP 5 was a bug, and it was fixed in PHP 7 when much of the engine changed.
 [2018-12-20 23:40 UTC] cmb@php.net
Shouldn't we trigger a notice/warning, if we ignore a call-by-ref
declaration?
 [2018-12-21 01:07 UTC] requinix@php.net
I don't think there should be. As far as I know the callback is being called with a reference correctly, however for $input to get the change, it (being the first argument to array_filter) would have to be a reference too.

Just like with a userland implementation, the by-ref $value is working, but since $input isn't a reference the change is happening on a copy. So no warning.

Also like a userland implementation, you can trick the engine by making $input's items references to something else. $input is still a copy but changing $value will work. Like
  $source = [1, 2];
  $input = [&$source[0], &$source[1]];
or
  foreach ($source as $key => $value) {
    $input[$key] =& $source[$key];
  }
 [2018-12-21 09:27 UTC] cmb@php.net
Ah, of course.  Thanks!
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 14:01:28 2024 UTC