Welcome! Log In Create A New Profile

Advanced

[PHP-DEV] BC break in 5.3.2 -> 5.3.3 with "parent::" and __call/__callStatic

Posted by Giovanni Giacobbi 
Greetings,

in reference to bug #52713 i'd like to inquire you about this decision which actually broke my codebase in different parts.

The situation is this one:

class ActiveRecord {

public function __call($method, $args) {
if ($method == "getFoo") {
// implement some default behaviour for getFoo()
}
}

public function __callStatic($method, $args) {
// do some other stuff
}
}


class Bar {
// override getFoo() to add some specific behaviour
public function getFoo() {
// do the specific stuff
parent::getFoo();
}
}


Until version 5.3.2 this worked fine, starting from version 5.3.3 parent::getFoo() calls __callStatic() instead of __call().

This is a really bad BC change which i thought you decided to accept only in minor versions change and not patch-level versions change.

Anyway, I would even be willing to do some changes to my codebase, but what is the solution? I can't see any other way to do this with the obvious assumptions that my design is good and that I don't know anything about the parent class except there is a getFoo() method implemented somehow.

My wish is that you restore the 5.3.2 behaviour, which sounds very reasonable, and maybe introduce another way when you actually want to get rid of the context, something like static::

--
Giovanni Giacobbi

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Hi!

> class Bar {
> // override getFoo() to add some specific behaviour
> public function getFoo() {
> // do the specific stuff
> parent::getFoo();
> }
> }

I think you meant Bar to extend ActiveRecord? But anyway, I think that
this particular call should be done through __call, not __callStatic,
since it's basically non-static call. The line between the two wasn't
really well-defined in PHP (you could call static methods non-statically
and vice versa) which is a pity but I think distinction can be made in
this case.

--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On Oct 24 15:41:44, Stas Malyshev wrote:
> Hi!
>
> >class Bar {
> > // override getFoo() to add some specific behaviour
> > public function getFoo() {
> > // do the specific stuff
> > parent::getFoo();
> > }
> >}
>
> I think you meant Bar to extend ActiveRecord? But anyway, I think
> that this particular call should be done through __call, not
> __callStatic, since it's basically non-static call. The line between
> the two wasn't really well-defined in PHP (you could call static
> methods non-statically and vice versa) which is a pity but I think
> distinction can be made in this case.

Exactly, if Bar::getFoo is not called statically, parent::getFoo() will
not be a static call, it should not get through __callStatic.

Best,

>
> --
> Stanislav Malyshev, Software Architect
> SugarCRM: http://www.sugarcrm.com/
> (408)454-6900 ext. 227
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>

--
Etienne Kneuss
http://www.colder.ch

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On Oct 25 0:56:28, Etienne Kneuss wrote:
> On Oct 24 15:41:44, Stas Malyshev wrote:
> > Hi!
> >
> > >class Bar {
> > > // override getFoo() to add some specific behaviour
> > > public function getFoo() {
> > > // do the specific stuff
> > > parent::getFoo();
> > > }
> > >}
> >
> > I think you meant Bar to extend ActiveRecord? But anyway, I think
> > that this particular call should be done through __call, not
> > __callStatic, since it's basically non-static call. The line between
> > the two wasn't really well-defined in PHP (you could call static
> > methods non-statically and vice versa) which is a pity but I think
> > distinction can be made in this case.
>
> Exactly, if Bar::getFoo is not called statically, parent::getFoo() will
> not be a static call, it should not get through __callStatic.
>
> Best,

Oh, and #51176 seems bogus to me. "::" is not sufficient to indicate a
static call, neither is "self::", "static::", or "Foo::".

A call is only static if one of the two following conditions match:
1) the target method is declared as static
2) the call comes from an object-less scope

>
> >
> > --
> > Stanislav Malyshev, Software Architect
> > SugarCRM: http://www.sugarcrm.com/
> > (408)454-6900 ext. 227
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php
> >
>
> --
> Etienne Kneuss
> http://www.colder.ch
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>

--
Etienne Kneuss
http://www.colder.ch

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On Mon, Oct 25, 2010 at 01:04:00AM +0200, Etienne Kneuss wrote:
> On Oct 25 0:56:28, Etienne Kneuss wrote:
> > >
> > > I think you meant Bar to extend ActiveRecord? But anyway, I think
> > > that this particular call should be done through __call, not
> > > __callStatic, since it's basically non-static call. The line between
> > > the two wasn't really well-defined in PHP (you could call static
> > > methods non-statically and vice versa) which is a pity but I think
> > > distinction can be made in this case.
> >
> > Exactly, if Bar::getFoo is not called statically, parent::getFoo() will
> > not be a static call, it should not get through __callStatic.
> >
> > Best,
>
> Oh, and #51176 seems bogus to me. "::" is not sufficient to indicate a
> static call, neither is "self::", "static::", or "Foo::".
>
> A call is only static if one of the two following conditions match:
> 1) the target method is declared as static
> 2) the call comes from an object-less scope
>

I think you perfectly got the point. However, being actually non-defined, we need to choose between __call() and __callStatic(), and i think that number 2 is the only applicable criteria.

Note that for my problem, reverting commit 295706 in branch PHP_5_3 is enough to fix my problem, but it would break again 51176.

As this is a BC break compared to the 5.3.x series, IMHO it's the right way to go and then find another solution for 51176.

--
Giovanni Giacobbi

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On Mon, Oct 25, 2010 at 12:56:28AM +0200, Etienne Kneuss wrote:

> Exactly, if Bar::getFoo is not called statically, parent::getFoo() will
> not be a static call, it should not get through __callStatic.

That logic sounds good. Unfortunately, things aren't behaving that way:

<?php

// Rework of code from http://bugs.php.net/bug.php?id=51176
class p {
public function __call($n, $a) {
echo "call\n";
}

public static function __callStatic($n, $a) {
echo "callStatic\n";
}
}

class c extends p {
public function existing() {
parent::non_existing();
}
}

$c = new c;
echo 'static = ';
c::s();
echo 'object = ';
$c->o();
echo 'parent = ';
$c->existing();

echo phpversion() . "\n";


Thanks,

--Dan

--
T H E A N A L Y S I S A N D S O L U T I O N S C O M P A N Y
data intensive web and database programming
http://www.AnalysisAndSolutions.com/
4015 7th Ave #4, Brooklyn NY 11232 v: 718-854-0335 f: 718-854-0409

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 26 October 2010 15:48, Daniel Convissor
<[email protected]> wrote:
> On Mon, Oct 25, 2010 at 12:56:28AM +0200, Etienne Kneuss wrote:
>
>> Exactly, if Bar::getFoo is not called statically, parent::getFoo() will
>> not be a static call, it should not get through __callStatic.
>
> That logic sounds good.  Unfortunately, things aren't behaving that way:
>
> <?php
>
> // Rework of code from http://bugs.php.net/bug.php?id=51176
> class p {
>        public function __call($n, $a) {
>                echo "call\n";
>        }
>
>        public static function __callStatic($n, $a) {
>                echo "callStatic\n";
>        }
> }
>
> class c extends p {
>        public function existing() {
>                parent::non_existing();
>        }
> }
>
> $c = new c;
> echo 'static = ';
> c::s();
> echo 'object = ';
> $c->o();
> echo 'parent = ';
> $c->existing();
>
> echo phpversion() . "\n";
>
>
> Thanks,
>
> --Dan

So the calling context/scope is going to have to be used to determine
if the call should get to __call or __callStatic.

Is that possible? Appropriate? Easy to do? Done by Friday?


--
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
2010/10/24 Giovanni Giacobbi <[email protected]>

>
> Greetings,
>
> in reference to bug #52713 i'd like to inquire you about this decision
> which actually broke my codebase in different parts.
>
> The situation is this one:
>
> class ActiveRecord {
>
> public function __call($method, $args) {
> if ($method == "getFoo") {
> // implement some default behaviour for getFoo()
> }
> }
>
> public function __callStatic($method, $args) {
> // do some other stuff
> }
> }
>
>
> class Bar {
> // override getFoo() to add some specific behaviour
> public function getFoo() {
> // do the specific stuff
> parent::getFoo();
> }
> }
>
>
> Until version 5.3.2 this worked fine, starting from version 5.3.3
> parent::getFoo() calls __callStatic() instead of __call().
>
> This is a really bad BC change which i thought you decided to accept only
> in minor versions change and not patch-level versions change.
>
> Anyway, I would even be willing to do some changes to my codebase, but what
> is the solution? I can't see any other way to do this with the obvious
> assumptions that my design is good and that I don't know anything about the
> parent class except there is a getFoo() method implemented somehow.
>
> My wish is that you restore the 5.3.2 behaviour, which sounds very
> reasonable, and maybe introduce another way when you actually want to get
> rid of the context, something like static::
>
>
The change has been reverted in SVN.


Thanks.

--
Regards,
Felipe Pena
> > Until version 5.3.2 this worked fine, starting from version 5.3.3
>> parent::getFoo() calls __callStatic() instead of __call().
>>
>> This is a really bad BC change which i thought you decided to accept only
>> in minor versions change and not patch-level versions change.
>>
>> Anyway, I would even be willing to do some changes to my codebase, but
>> what
>> is the solution? I can't see any other way to do this with the obvious
>> assumptions that my design is good and that I don't know anything about
>> the
>> parent class except there is a getFoo() method implemented somehow.
>>
>> My wish is that you restore the 5.3.2 behaviour, which sounds very
>> reasonable, and maybe introduce another way when you actually want to get
>> rid of the context, something like static::
>>
>>
> The change has been reverted in SVN.
>

Great. Is there any chance to see 5.3.4 anytime soon?

-j



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sorry, only registered users may post in this forum.

Click here to login