Hi,
I'm having a cause of slightly ugly code that runs differently from PHP 5.6
to PHP 7 and I don't think this difference is documented, nor expected. As
I'm not sure whether this is an intended change or not, I'm asking here
firstr before making a bug report.
The code in question is
$b = [1, 2, 3];
foreach($b ?: [] as &$v){
$v = $v*2;
unset($v);
}
var_dump($b);
in PHP7, this produces
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}
whereas in PHP 5.6 and earlier, this produces
array(3) {
[0] =>
int(2)
[1] =>
int(4)
[2] =>
int(6)
}
what scares me about this is that in order to get the old behaviour in PHP7
back, you just have to get rid of the ?: operator:
foreach($b as &$v){
is fine
foreach($b ?: [] as &$v){
is not.
I guess this is related to
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-value
or
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-ref,
but I'm not entirely sure whether this is actually intended behaviour -
it's certainly unexpected to me that applying ?: now always makes a copy
whereas before it didn't.
Philip
--
Sensational AG
Giesshübelstrasse 62c, Postfach 1966, 8021 Zürich
Tel. +41 43 544 09 60, Mobile +41 79 341 01 99
info@sensational.ch, http://www.sensational.ch
Here’s a 3v4l demonstrating this too:
https://3v4l.org/OXAd3 https://3v4l.org/OXAd3
Hi,
I'm having a cause of slightly ugly code that runs differently from PHP 5.6
to PHP 7 and I don't think this difference is documented, nor expected. As
I'm not sure whether this is an intended change or not, I'm asking here
firstr before making a bug report.The code in question is
$b = [1, 2, 3];
foreach($b ?: [] as &$v){
$v = $v*2;
unset($v);
}var_dump($b);
in PHP7, this produces
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}whereas in PHP 5.6 and earlier, this produces
array(3) {
[0] =>
int(2)
[1] =>
int(4)
[2] =>
int(6)
}what scares me about this is that in order to get the old behaviour in PHP7
back, you just have to get rid of the ?: operator:foreach($b as &$v){
is fine
foreach($b ?: [] as &$v){
is not.
I guess this is related to
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-value
or
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-ref,
but I'm not entirely sure whether this is actually intended behaviour -
it's certainly unexpected to me that applying ?: now always makes a copy
whereas before it didn't.Philip
--
Sensational AG
Giesshübelstrasse 62c, Postfach 1966, 8021 Zürich
Tel. +41 43 544 09 60, Mobile +41 79 341 01 99
info@sensational.ch, http://www.sensational.ch
On Tue, Nov 10, 2015 at 11:48 AM, Philip Hofstetter <
phofstetter@sensational.ch> wrote:
Hi,
...snip...
I guess this is related tohttp://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-value
orhttp://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-ref
,
but I'm not entirely sure whether this is actually intended behaviour -
it's certainly unexpected to me that applying ?: now always makes a copy
whereas before it didn't.
The issue may not be with foreach, but instead with the ?: ternary or the
optimizer. Maybe either:
-
It's a side-effect of merging the ZEND_QM_ASSIGN and ZEND_QM_ASSIGN_VAR
op codes. (See PHP 5.6 ?: op code definitions
https://github.com/php/php-src/blob/PHP-5.6/Zend/zend_vm_def.h#L4977-L5021
and Same for PHP 7.0
https://github.com/php/php-src/blob/master/Zend/zend_vm_def.h#L6945-L6977
.) -
The optimizer isn't handling the foreach scenario. (See Block pass
optimizer code
https://github.com/php/php-src/blob/master/ext/opcache/Optimizer/block_pass.c#L574-L593
.)
I don't see any change notes for either, so I'm guessing this is a bug.
bishop
On Tue, Nov 10, 2015 at 5:48 PM, Philip Hofstetter <
phofstetter@sensational.ch> wrote:
Hi,
I'm having a cause of slightly ugly code that runs differently from PHP 5.6
to PHP 7 and I don't think this difference is documented, nor expected. As
I'm not sure whether this is an intended change or not, I'm asking here
firstr before making a bug report.The code in question is
$b = [1, 2, 3];
foreach($b ?: [] as &$v){
$v = $v*2;
unset($v);
}var_dump($b);
in PHP7, this produces
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}whereas in PHP 5.6 and earlier, this produces
array(3) {
[0] =>
int(2)
[1] =>
int(4)
[2] =>
int(6)
}what scares me about this is that in order to get the old behaviour in PHP7
back, you just have to get rid of the ?: operator:foreach($b as &$v){
is fine
foreach($b ?: [] as &$v){
is not.
I guess this is related to
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-value
orhttp://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-ref
,
but I'm not entirely sure whether this is actually intended behaviour -
it's certainly unexpected to me that applying ?: now always makes a copy
whereas before it didn't.
This is a bug in PHP 5, which has been fixed in PHP 7 as a side-effect of
other changes. The new behavior is correct. This issue is tracked at
https://bugs.php.net/bug.php?id=70857.
Nikita
Hey Nikita,
This is a bug in PHP 5, which has been fixed in PHP 7 as a side-effect of
other changes. The new behavior is correct. This issue is tracked at
https://bugs.php.net/bug.php?id=70857.
Are there any other variations on what expressions this changes the
behaviour of, or is it really just ternaries? Just trying to figure
out how to document this.
Thanks,
Adam
Should this be in the UPGRADING notes?
On Tue, Nov 10, 2015 at 5:48 PM, Philip Hofstetter <
phofstetter@sensational.ch> wrote:Hi,
I'm having a cause of slightly ugly code that runs differently from PHP 5.6
to PHP 7 and I don't think this difference is documented, nor expected. As
I'm not sure whether this is an intended change or not, I'm asking here
firstr before making a bug report.The code in question is
$b = [1, 2, 3];
foreach($b ?: [] as &$v){
$v = $v*2;
unset($v);
}var_dump($b);
in PHP7, this produces
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}whereas in PHP 5.6 and earlier, this produces
array(3) {
[0] =>
int(2)
[1] =>
int(4)
[2] =>
int(6)
}what scares me about this is that in order to get the old behaviour in PHP7
back, you just have to get rid of the ?: operator:foreach($b as &$v){
is fine
foreach($b ?: [] as &$v){
is not.
I guess this is related to
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-value
orhttp://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.foreach.by-ref
,
but I'm not entirely sure whether this is actually intended behaviour -
it's certainly unexpected to me that applying ?: now always makes a copy
whereas before it didn't.This is a bug in PHP 5, which has been fixed in PHP 7 as a side-effect of
other changes. The new behavior is correct. This issue is tracked at
https://bugs.php.net/bug.php?id=70857.Nikita