PHP 5.2-dev "Cannot use array returned from foo::__get('bar') in write context"

php.internals

Christian Stocker

20 years ago
Just updated to the latest PHP 5.2-dev from CVS and now I get an Fatal error with the following code *** <?php class foo { public function __get($member) { return array("foo"=>"bar","bar"=>"foo"); } } $f = new foo(); //error foreach($f->bar as $key => $value) { print "$key => $value"; } ?> *** It throws a "Fatal error: Cannot use array returned from foo::__get('bar') in write context" on the foreach line. Quite annoying :) That worked fine with 5.1 and also with 5.2-dev from a few days/weeks ago (don't know, when I cvs-uped last time, but can't be that long) Is that expected/wished behaviour? chregu
-- christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB

Richard Quadling

20 years ago
For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... Fatal error: Cannot use array returned from foo::__get('bar') in write context in C:\- on line 16 But only once, not 1 per line. $f = new foo(); $a = $f->bar; foreach($a as $key => $value) fixes the code. On 19/07/06, Christian Stocker <christian.stocker@bitflux.ch> wrote:
> Just updated to the latest PHP 5.2-dev from CVS and now I get an Fatal > error with the following code > *** > <?php > > class foo { > public function __get($member) { > return array("foo"=>"bar","bar"=>"foo"); > } > } > > $f = new foo(); > > //error > foreach($f->bar as $key => $value) { > print "$key => $value"; > } > > ?> > *** > > It throws a > > "Fatal error: Cannot use array returned from foo::__get('bar') in write > context" > > on the foreach line. Quite annoying :) > > > That worked fine with 5.1 and also with 5.2-dev from a few days/weeks > ago (don't know, when I cvs-uped last time, but can't be that long) > > Is that expected/wished behaviour? > > chregu > > > > > -- > christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich > phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 > http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- ----- Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&amp;r=213474731

Christian Stocker

20 years ago
On 19.7.2006 15:24 Uhr, Richard Quadling wrote:
> For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... > > Fatal error: Cannot use array returned from foo::__get('bar') in write > context in C:\- on line 16 > > But only once, not 1 per line. > > $f = new foo(); > $a = $f->bar; > foreach($a as $key => $value) > > fixes the code. >
I know (forgot to mention it), but still annoying as I have to fix a lot of lines to do that. If there are technical reasons for the fatal error, fine, I have to live with it then. But I still hope, it's just an overlook somewhere :) chregu
> > > On 19/07/06, Christian Stocker <christian.stocker@bitflux.ch> wrote: >> Just updated to the latest PHP 5.2-dev from CVS and now I get an Fatal >> error with the following code >> *** >> <?php >> >> class foo { >> public function __get($member) { >> return array("foo"=>"bar","bar"=>"foo"); >> } >> } >> >> $f = new foo(); >> >> //error >> foreach($f->bar as $key => $value) { >> print "$key => $value"; >> } >> >> ?> >> *** >> >> It throws a >> >> "Fatal error: Cannot use array returned from foo::__get('bar') in write >> context" >> >> on the foreach line. Quite annoying :) >> >> >> That worked fine with 5.1 and also with 5.2-dev from a few days/weeks >> ago (don't know, when I cvs-uped last time, but can't be that long) >> >> Is that expected/wished behaviour? >> >> chregu >> >> >> >> >> -- >> christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich >> phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 >> http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> >> > >
-- christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB

Pierre Joye

20 years ago
On Wed, 19 Jul 2006 15:32:42 +0200 christian.stocker@bitflux.ch (Christian Stocker) wrote:
> > > On 19.7.2006 15:24 Uhr, Richard Quadling wrote: > > For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... > > > > Fatal error: Cannot use array returned from foo::__get('bar') in > > write context in C:\- on line 16 > > > > But only once, not 1 per line. > > > > $f = new foo(); > > $a = $f->bar; > > foreach($a as $key => $value) > > > > fixes the code. > > > > I know (forgot to mention it), but still annoying as I have to fix a > lot of lines to do that. > > If there are technical reasons for the fatal error, fine, I have to > live with it then.
If there is good reasons for this change, it should be a good candidate for E_STRICT but not E_FATAL/RECOVERABLE. We should also have a notice in the upgrading notes. I can do it as soon as we agreed on a solution. -- Pierre

Dmitry Stogov

20 years ago
__get() never worked in write context proper. It just CAN NOT work proper, because __get() returns by value (zval*), but modification requires address (zval**). We have a lot of __get() related bugs because of this situation in bugs.php.net. Month ago Marcus disabled usage of __get() in write context and I am completely agree with him We cannot use E_STRICT for this error and then SIGSEGV. Thanks. Dmitry.

Michael Wallner

20 years ago
Dmitry Stogov wrote:
> __get() never worked in write context proper. It just CAN NOT work > proper, because __get() returns by value (zval*), but modification > requires address (zval**). We have a lot of __get() related bugs > because of this situation in bugs.php.net. > > Month ago Marcus disabled usage of __get() in write context and I am > completely agree with him We cannot use E_STRICT for this error and > then SIGSEGV.
I agree with you and Marcus here, but since when does foreach() need write context? Maybe just a weird idea, but what about a &__ref(name) overload function?
-- Michael

Christian Stocker

20 years ago
On 19.7.2006 17:22 Uhr, Dmitry Stogov wrote:
> __get() never worked in write context proper. > It just CAN NOT work proper, because __get() returns by value (zval*), but > modification requires address (zval**). > We have a lot of __get() related bugs because of this situation in > bugs.php.net.
Fine, but I'm now wondering, where's the write context in foreach($f->bar as $key => $value) { } Just wondering as the error message is very missleading for a core-outsider, which only sees reads from that array and no modifications to it. chregu, off to change its code now :)
-- christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB

Pierre Joye

20 years ago
On Wed, 19 Jul 2006 19:22:47 +0400 dmitry@zend.com ("Dmitry Stogov") wrote:
> __get() never worked in write context proper. > It just CAN NOT work proper, because __get() returns by value > (zval*), but modification requires address (zval**). > We have a lot of __get() related bugs because of this situation in > bugs.php.net. > > Month ago Marcus disabled usage of __get() in write context and I am > completely agree with him > We cannot use E_STRICT for this error and then SIGSEGV.
I agree too with the write mode. What I do not really understand is why this script produces a write mode, there is actually no write operations outside the hash position. For what Dmitri explained, foreach uses array in write context. It is required when foreach is done by ref. The open question is to know if it is possible to work in read mode in this case. Please reopen or create a bug report about this issue and assign it to Dmitri (requested by Dmitri). Cheers, -- Pierre

Christian Stocker

20 years ago
On 19.7.2006 17:59 Uhr, Pierre wrote:
> On Wed, 19 Jul 2006 19:22:47 +0400 > dmitry@zend.com ("Dmitry Stogov") wrote: > >> __get() never worked in write context proper. >> It just CAN NOT work proper, because __get() returns by value >> (zval*), but modification requires address (zval**). >> We have a lot of __get() related bugs because of this situation in >> bugs.php.net. >> >> Month ago Marcus disabled usage of __get() in write context and I am >> completely agree with him >> We cannot use E_STRICT for this error and then SIGSEGV. > > I agree too with the write mode. What I do not really understand is why > this script produces a write mode, there is actually no write > operations outside the hash position. > > For what Dmitri explained, foreach uses array in write context. It is > required when foreach is done by ref. > > The open question is to know if it is possible to work in read mode in > this case. > > Please reopen or create a bug report about this issue and assign it to > Dmitri (requested by Dmitri).
done: http://bugs.php.net/bug.php?id=38146 chregu
> > Cheers, > -- Pierre >
-- christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB

Andrei Zmievski

20 years ago
But how is foreach() a write context? Unless you mean that someone uses foreach($f->bar as &$val) { .. }. Can we detect that though? -Andrei On Jul 19, 2006, at 8:22 AM, Dmitry Stogov wrote:

Dmitry Stogov

20 years ago
Of course we can. I'll look into the problem. Dmitry.

Marcus Börger

20 years ago
Hello Andrei, the problem is not the 'as' part, the problem is accessing the array and that currently must be a write context. Maybe we can work around tha at some point i dunno. best regards marcus Wednesday, July 19, 2006, 6:24:02 PM, you wrote:
> But how is foreach() a write context? Unless you mean that someone uses > foreach($f->bar as &$val) { .. }. Can we detect that though?
> -Andrei
> On Jul 19, 2006, at 8:22 AM, Dmitry Stogov wrote:
>> __get() never worked in write context proper. >> It just CAN NOT work proper, because __get() returns by value (zval*), >> but >> modification requires address (zval**). >> We have a lot of __get() related bugs because of this situation in >> bugs.php.net. >> >> Month ago Marcus disabled usage of __get() in write context and I am >> completely agree with him >> We cannot use E_STRICT for this error and then SIGSEGV. >> >> Thanks. Dmitry. >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php
Best regards, Marcus

Andi Gutmans

20 years ago
We were considering supporting a __getRef() method. You could implement either or both of them and then the right thing would happen. Dmitry, Marcus - Besides having to come to a decision about this, is there any situation you guys discussed for which this would not work? Thx. Andi

Marcus Börger

20 years ago
Hello Andi, the question was how to implement this as a c ref is a pointer, in case of zval*'s it is a zval** but in php a ref is a zval with is_ref=1. If we go with php refs then we would convert all variables to refs. Now i wonder if we could chang the return type to be a c reference only, can we do that? And is it even wanted? Since if it were easily possible, why aren't we doing that everywhere? It would solve a bunch of issues... best regards marcus Thursday, July 20, 2006, 7:40:37 AM, you wrote:
> We were considering supporting a __getRef() method. You could implement > either or both of them and then the right thing would happen. > Dmitry, Marcus - Besides having to come to a decision about this, is there > any situation you guys discussed for which this would not work?
> Thx.
> Andi
>> -----Original Message----- >> From: Dmitry Stogov [mailto:dmitry@zend.com] >> Sent: Wednesday, July 19, 2006 8:23 AM >> To: internals@lists.php.net >> Cc: Marcus Boerger; Andi Gutmans >> Subject: RE: [PHP-DEV] PHP 5.2-dev "Cannot use array returned >> from foo::__get('bar') in write context" >> >> __get() never worked in write context proper. >> It just CAN NOT work proper, because __get() returns by value >> (zval*), but modification requires address (zval**). >> We have a lot of __get() related bugs because of this >> situation in bugs.php.net. >> >> Month ago Marcus disabled usage of __get() in write context >> and I am completely agree with him We cannot use E_STRICT for >> this error and then SIGSEGV. >> >> Thanks. Dmitry. >> >> >> >> >>
Best regards, Marcus

Ron Korving

20 years ago
Can't you make it so that PHP internally uses a "nameless" variable in which it stores the result of the __get() before it continues to do anything with it? I may be too much of a rookie here, but it seems to me that that could solve a lot of problems. You could even write to it (if you'd allow writing to a nameless variable which doesn't make sense, but could be allowed). Basically you'd internally be interpreting: foreach ($obj->somevar as $foo => $bar) { } as: $_ = $obj->somevar; foreach ($_ as $foo => $bar) { } or would that present other problems I don't see? This doesn't solve it when you wanna write to a virtual __get variable, but in a read-only situation, I as a user wouldn't want to implement a __getRef(), it wouldn't make sense from a user perspective. - Ron ""Andi Gutmans"" <andi@zend.com> schreef in bericht news:004701c6abbf$08c5ecd0$6600a8c0@zend.2k...

Marcus Börger

20 years ago
Hello Ron, the $_ would right now involve a deep copy which we try to avoid. We just have to review the code and see what we can do about that. Maybe a thing to do while in RC1 or a reason to postpone RC1. With discussions like Date and Zip i'd say the latter and eventually have both in as it means enough time to discuss both (Ilia?). best regards marcus Thursday, July 20, 2006, 9:33:26 AM, you wrote:
> Can't you make it so that PHP internally uses a "nameless" variable in which > it stores the result of the __get() before it continues to do anything with > it? I may be too much of a rookie here, but it seems to me that that could > solve a lot of problems. You could even write to it (if you'd allow writing > to a nameless variable which doesn't make sense, but could be allowed).
> Basically you'd internally be interpreting:
> foreach ($obj->somevar as $foo => $bar) > { > }
> as:
> $_ = $obj->somevar; > foreach ($_ as $foo => $bar) > { > }
> or would that present other problems I don't see? This doesn't solve it when > you wanna write to a virtual __get variable, but in a read-only situation, I > as a user wouldn't want to implement a __getRef(), it wouldn't make sense > from a user perspective.
> - Ron
> ""Andi Gutmans"" <andi@zend.com> schreef in bericht > news:004701c6abbf$08c5ecd0$6600a8c0@zend.2k... >> We were considering supporting a __getRef() method. You could implement >> either or both of them and then the right thing would happen. >> Dmitry, Marcus - Besides having to come to a decision about this, is there >> any situation you guys discussed for which this would not work? >> >> Thx. >> >> Andi >> >>> -----Original Message----- >>> From: Dmitry Stogov [mailto:dmitry@zend.com] >>> Sent: Wednesday, July 19, 2006 8:23 AM >>> To: internals@lists.php.net >>> Cc: Marcus Boerger; Andi Gutmans >>> Subject: RE: [PHP-DEV] PHP 5.2-dev "Cannot use array returned >>> from foo::__get('bar') in write context" >>> >>> __get() never worked in write context proper. >>> It just CAN NOT work proper, because __get() returns by value >>> (zval*), but modification requires address (zval**). >>> We have a lot of __get() related bugs because of this >>> situation in bugs.php.net. >>> >>> Month ago Marcus disabled usage of __get() in write context >>> and I am completely agree with him We cannot use E_STRICT for >>> this error and then SIGSEGV. >>> >>> Thanks. Dmitry. >>> >>> >>> >>> >>>
Best regards, Marcus

Marcus Börger

20 years ago
Hello Pierre, Wednesday, July 19, 2006, 3:56:15 PM, you wrote:
> On Wed, 19 Jul 2006 15:32:42 +0200 > christian.stocker@bitflux.ch (Christian Stocker) wrote:
>> >> >> On 19.7.2006 15:24 Uhr, Richard Quadling wrote: >> > For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... >> > >> > Fatal error: Cannot use array returned from foo::__get('bar') in >> > write context in C:\- on line 16 >> > >> > But only once, not 1 per line. >> > >> > $f = new foo(); >> > $a = $f->bar; >> > foreach($a as $key => $value) >> > >> > fixes the code. >> > >> >> I know (forgot to mention it), but still annoying as I have to fix a >> lot of lines to do that. >> >> If there are technical reasons for the fatal error, fine, I have to >> live with it then.
> If there is good reasons for this change, it should be a good candidate > for E_STRICT but not E_FATAL/RECOVERABLE.
Wrong answer and not an option at all - sorry. But we are actually preventing potential SEGVs here. Just like the mighty reference thing that lead to PHP 4.4.
> We should also have a notice in the upgrading notes. I can do it as > soon as we agreed on a solution.
Why not write one since you are obviously aware of this. I wasn't until this very momnet as i never use __get(), since i know it has too many issues and causes to many problems. So here i am probbaly the wrong person to write something. Best regards, Marcus

Pierre Joye

20 years ago
On 7/19/06, Marcus Boerger <helly@php.net> wrote:
> Hello Pierre, > > Wednesday, July 19, 2006, 3:56:15 PM, you wrote: > > > On Wed, 19 Jul 2006 15:32:42 +0200 > > christian.stocker@bitflux.ch (Christian Stocker) wrote: > > >> > >> > >> On 19.7.2006 15:24 Uhr, Richard Quadling wrote: > >> > For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... > >> > > >> > Fatal error: Cannot use array returned from foo::__get('bar') in > >> > write context in C:\- on line 16 > >> > > >> > But only once, not 1 per line. > >> > > >> > $f = new foo(); > >> > $a = $f->bar; > >> > foreach($a as $key => $value) > >> > > >> > fixes the code. > >> > > >> > >> I know (forgot to mention it), but still annoying as I have to fix a > >> lot of lines to do that. > >> > >> If there are technical reasons for the fatal error, fine, I have to > >> live with it then. > > > If there is good reasons for this change, it should be a good candidate > > for E_STRICT but not E_FATAL/RECOVERABLE. > > Wrong answer and not an option at all - sorry. But we are actually > preventing potential SEGVs here. Just like the mighty reference thing that > lead to PHP 4.4.
You don't have to answer in a bad way when Dmitry nicely already explained the reasons. Especially when we all agreed on the main cause.
> Why not write one since you are obviously aware of this. I wasn't until this > very momnet as i never use __get(), since i know it has too many issues and > causes to many problems. So here i am probbaly the wrong person to write > something.
I retire my offer, do it yourself, you know it better. And you should have done it in the first place. --Pierre

Marcus Börger

20 years ago
Hello Pierre, Wednesday, July 19, 2006, 9:42:54 PM, you wrote:
> On 7/19/06, Marcus Boerger <helly@php.net> wrote: >> Hello Pierre, >> >> Wednesday, July 19, 2006, 3:56:15 PM, you wrote: >> >> > On Wed, 19 Jul 2006 15:32:42 +0200 >> > christian.stocker@bitflux.ch (Christian Stocker) wrote: >> >> >> >> >> >> >> On 19.7.2006 15:24 Uhr, Richard Quadling wrote: >> >> > For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... >> >> > >> >> > Fatal error: Cannot use array returned from foo::__get('bar') in >> >> > write context in C:\- on line 16 >> >> > >> >> > But only once, not 1 per line. >> >> > >> >> > $f = new foo(); >> >> > $a = $f->bar; >> >> > foreach($a as $key => $value) >> >> > >> >> > fixes the code. >> >> > >> >> >> >> I know (forgot to mention it), but still annoying as I have to fix a >> >> lot of lines to do that. >> >> >> >> If there are technical reasons for the fatal error, fine, I have to >> >> live with it then. >> >> > If there is good reasons for this change, it should be a good candidate >> > for E_STRICT but not E_FATAL/RECOVERABLE. >> >> Wrong answer and not an option at all - sorry. But we are actually >> preventing potential SEGVs here. Just like the mighty reference thing that >> lead to PHP 4.4.
> You don't have to answer in a bad way when Dmitry nicely already > explained the reasons. Especially when we all agreed on the main > cause.
I only tried to explain that this situation does not fall in the category where E_STRICT is the answer and then gave a short explanation.
>> Why not write one since you are obviously aware of this. I wasn't until this >> very momnet as i never use __get(), since i know it has too many issues and >> causes to many problems. So here i am probbaly the wrong person to write >> something.
> I retire my offer, do it yourself, you know it better. And you should > have done it in the first place.
Wow great. And later you i am the idiot to blame or what? Thanks for the help. Best regards, Marcus

Mike Bretz

20 years ago
I guess this is associated with bug #36647 ( http://bugs.php.net/bug.php?id=36647 ) and I do not think that this makes a lot sense for the applications outside and will break them. For my company I decided that __get handlers really suck and I do not encourage our developers to use it anymore. I strongly request that the whole part of __* handlers gets revisited, especially for memory allocation bugs (see my bugreport). I do not see any benefit of having those methods when the methods either refuse to do things which were possible before(BC!), nor when they do trash the application like now in current release. Leaving the methods untouched is a bad thing, since for security reasons the memleaks should be fixed asap. But "disabling" some of the functionality (return an internal array of the class for further handling) is not that nice at all, too. A smarter way has to be found, pls - if at all possible (derrick told me that this is "by php design" and probably is unfixable by nature). mike Richard Quadling wrote:
> For PHP 5.2.0-dev (cli) (built: Jul 12 2006 12:20:25), I get ... > > Fatal error: Cannot use array returned from foo::__get('bar') in write > context in C:\- on line 16 > > But only once, not 1 per line. > > $f = new foo(); > $a = $f->bar; > foreach($a as $key => $value) > > fixes the code. > > > > On 19/07/06, Christian Stocker <christian.stocker@bitflux.ch> wrote: >> Just updated to the latest PHP 5.2-dev from CVS and now I get an Fatal >> error with the following code >> *** >> <?php >> >> class foo { >> public function __get($member) { >> return array("foo"=>"bar","bar"=>"foo"); >> } >> } >> >> $f = new foo(); >> >> //error >> foreach($f->bar as $key => $value) { >> print "$key => $value"; >> } >> >> ?> >> *** >> >> It throws a >> >> "Fatal error: Cannot use array returned from foo::__get('bar') in write >> context" >> >> on the foreach line. Quite annoying :) >> >> >> That worked fine with 5.1 and also with 5.2-dev from a few days/weeks >> ago (don't know, when I cvs-uped last time, but can't be that long) >> >> Is that expected/wished behaviour? >> >> chregu >> >> >> >> >> -- >> christian stocker | Bitflux GmbH | schoeneggstrasse 5 | ch-8004 zurich >> phone +41 44 240 56 70 | mobile +41 76 561 88 60 | fax +41 1 240 56 71 >> http://www.bitflux.ch | christian.stocker@bitflux.ch | GPG 0x5CE1DECB >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> >> > >
-- mike peter bretz metropolis ag / entwicklung email: m.bretz@metropolis-ag.de heinestraße 72 phone: +49-7121-348-120 d-72762 reutlingen fax: +49-7121-348-111 http://www.metropolis-ag.de/ metropolis ag. creating social internetworks.