Hello,
Currently, those are allowed:
new $classname;
classname::$methodname();
but those aren't:
$classname::foo();
$classname::CONST;
$classname::$member;
Here is a patch for head that fixes those inconsistencies by extending
the language parser to support such syntax:
http://patches.colder.ch/Zend/dynamic_static_calls.patch?markup (patch
also attached)
Regards
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hi Etienne,
Hello,
Currently, those are allowed:
new $classname;
classname::$methodname();but those aren't:
$classname::foo();
$classname::CONST;
$classname::$member;Here is a patch for head that fixes those inconsistencies by extending
the language parser to support such syntax:
thanks for this fix.
Ilia, do you mind MFHing this fix before the next 5.2 release? Then I'd
commit it within the next days.
johannes
http://patches.colder.ch/Zend/dynamic_static_calls.patch?markup (patch
also attached)Regards
plain text document attachment (dynamic_static_calls.patch)
Index: Zend/zend_language_parser.yRCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.186
diff -u -p -r1.186 zend_language_parser.y
--- Zend/zend_language_parser.y 27 Jul 2007 09:04:12 -0000 1.186
+++ Zend/zend_language_parser.y 30 Jul 2007 20:28:41 -0000
@@ -649,6 +649,12 @@ function_call:
| fully_qualified_class_nameT_PAAMAYIM_NEKUDOTAYIM
T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }function_call_parameter_list
| fully_qualified_class_name')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
T_PAAMAYIM_NEKUDOTAYIM
variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
@@ -809,6 +815,11 @@ variable_without_objects:static_member:
fully_qualified_class_nameT_PAAMAYIM_NEKUDOTAYIM
variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
+;+variable_class_name:
- reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$=$1;}
;@@ -935,6 +946,7 @@ isset_variables:
class_constant:
fully_qualified_class_nameT_PAAMAYIM_NEKUDOTAYIM
T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
;%%
Index: tests/lang/041.phptRCS file: tests/lang/041.phpt
diff -N tests/lang/041.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/041.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,23 @@
+--TEST--
+Dynamic access of static members
+--FILE--
+<?php
+class A {
- public static $b = 'foo';
+}+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';
+echo $classname::$b."\n";
+echo $binaryClassname::$b."\n";
+echo $wrongClassname::$b."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+Fatal error: Class 'B' not found in %s041.php on line %d
Index: tests/lang/042.phptRCS file: tests/lang/042.phpt
diff -N tests/lang/042.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/042.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,22 @@
+--TEST--
+Dynamic access of constants
+--FILE--
+<?php
+class A {
- const B = 'foo';
+}+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';
+echo $classname::B."\n";
+echo $binaryClassname::B."\n";
+echo $wrongClassname::B."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+Fatal error: Class 'B' not found in %s042.php on line %d
Index: tests/lang/043.phptRCS file: tests/lang/043.phpt
diff -N tests/lang/043.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/043.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,22 @@
+--TEST--
+Dynamic call for static methods
+--FILE--
+<?php
+class A {
- static function foo() { return 'foo'; }
+}+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';
+echo $classname::foo()."\n";
+echo $binaryClassname::foo()."\n";
+echo $wrongClassname::foo()."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+Fatal error: Class 'B' not found in %s043.php on line %d
Index: tests/lang/044.phptRCS file: tests/lang/044.phpt
diff -N tests/lang/044.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/044.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,30 @@
+--TEST--
+Dynamic call for static methods dynamically named
+--FILE--
+<?php
+class A {
- static function foo() { return 'foo'; }
+}
+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';+$methodname = 'foo';
+$binaryMethodname = b'foo';
+echo $classname::$methodname()."\n";
+echo $classname::$binaryMethodname()."\n";
+echo $binaryClassname::$methodname()."\n";
+echo $binaryClassname::$binaryMethodname()."\n";
+echo $wrongClassname::$binaryMethodname()."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+foo
+foo
+Fatal error: Class 'B' not found in %s044.php on line %d
This is not really a fix.
When we worked on PHP 5 we deliberately decided to relax on all the weird dynamic constructs which didn't provide a lot of value for the majority of use-cases. Of course the Reflection API was going to be the way to do these dynamic things in future. It would also simplify the engine's code. The reason why those first constructs work were for BC reasons. We didn't want to break existing code but wanted to not add on top of this.
While it may feel inconsistent I still prefer the existing path. Maybe for PHP 6 we can even make an E_STRICT
message for the old way which refers you to the Reflection API?
Andi
-----Original Message-----
From: Johannes Schlüter [mailto:johannes@php.net]
Sent: Tuesday, July 31, 2007 4:57 AM
To: Etienne Kneuss
Cc: internals@lists.php.net; Ilia Alshanetsky
Subject: Re: [PHP-DEV] Fix inconsistencies in OO callsHi Etienne,
Hello,
Currently, those are allowed:
new $classname;
classname::$methodname();but those aren't:
$classname::foo();
$classname::CONST;
$classname::$member;Here is a patch for head that fixes those inconsistencies
by extending
the language parser to support such syntax:thanks for this fix.
Ilia, do you mind MFHing this fix before the next 5.2
release? Then I'd commit it within the next days.johannes
http://patches.colder.ch/Zend/dynamic_static_calls.patch?marku
p (patchalso attached)
Regards
plain text document attachment (dynamic_static_calls.patch)
Index: Zend/zend_language_parser.yRCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.186
diff -u -p -r1.186 zend_language_parser.y
--- Zend/zend_language_parser.y 27 Jul 2007 09:04:12
-0000 1.186
+++ Zend/zend_language_parser.y 30 Jul 2007 20:28:41 -0000
@@ -649,6 +649,12 @@ function_call:
| fully_qualified_class_name
T_PAAMAYIM_NEKUDOTAYIM
T_STRING '(' {
zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL,
&$$, &$6, 1, 1 TSRMLS_CC);
zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
T_STRING
'(' { zend_do_begin_class_member_function_call(&$1,
&$3 TSRMLS_CC); }function_call_parameter_list
')' { zend_do_end_function_call(NULL,
&$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
variable_without_objects '(' {
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }function_call_parameter_list
')' { zend_do_end_function_call(NULL,
&$$, &$6, 1, 1 TSRMLS_CC);
+zend_do_extended_fcall_end(TSRMLS_C);}
| fully_qualified_class_name
T_PAAMAYIM_NEKUDOTAYIM
variable_without_objects '(' {
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL,
&$$, &$6, 1, 1 TSRMLS_CC);
zend_do_extended_fcall_end(TSRMLS_C);}
@@ -809,6 +815,11 @@ variable_without_objects:static_member:
fully_qualified_class_nameT_PAAMAYIM_NEKUDOTAYIM
variable_without_objects { $$ = $3;
zend_do_fetch_static_member(&$$,
&$1 TSRMLS_CC); }
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
variable_without_objects { $$ = $3;
zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
+;+variable_class_name:
- reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0
+TSRMLS_CC); $$=$1;}
;@@ -935,6 +946,7 @@ isset_variables:
class_constant:
fully_qualified_class_name
T_PAAMAYIM_NEKUDOTAYIM
T_STRING {
zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
- | variable_class_name
T_PAAMAYIM_NEKUDOTAYIM
T_STRING
{ zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT TSRMLS_CC); }
;%%
Index: tests/lang/041.phptRCS file: tests/lang/041.phpt
diff -N tests/lang/041.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/041.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,23 @@
+--TEST--
+Dynamic access of static members
+--FILE--
+<?php
+class A {
- public static $b = 'foo';
+}+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';
+echo $classname::$b."\n";
+echo $binaryClassname::$b."\n";
+echo $wrongClassname::$b."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+Fatal error: Class 'B' not found in %s041.php on line %d
Index: tests/lang/042.phptRCS file: tests/lang/042.phpt
diff -N tests/lang/042.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/042.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,22 @@
+--TEST--
+Dynamic access of constants
+--FILE--
+<?php
+class A {
- const B = 'foo';
+}+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';
+echo $classname::B."\n";
+echo $binaryClassname::B."\n";
+echo $wrongClassname::B."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+Fatal error: Class 'B' not found in %s042.php on line %d
Index: tests/lang/043.phptRCS file: tests/lang/043.phpt
diff -N tests/lang/043.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/043.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,22 @@
+--TEST--
+Dynamic call for static methods
+--FILE--
+<?php
+class A {
- static function foo() { return 'foo'; } }
+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';
+echo $classname::foo()."\n";
+echo $binaryClassname::foo()."\n";
+echo $wrongClassname::foo()."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+Fatal error: Class 'B' not found in %s043.php on line %d
Index: tests/lang/044.phptRCS file: tests/lang/044.phpt
diff -N tests/lang/044.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/044.phpt 30 Jul 2007 20:28:41 -0000
@@ -0,0 +1,30 @@
+--TEST--
+Dynamic call for static methods dynamically named
+--FILE--
+<?php
+class A {
- static function foo() { return 'foo'; } }
+$classname = 'A';
+$binaryClassname = b'A';
+$wrongClassname = 'B';+$methodname = 'foo';
+$binaryMethodname = b'foo';
+echo $classname::$methodname()."\n";
+echo $classname::$binaryMethodname()."\n";
+echo $binaryClassname::$methodname()."\n";
+echo $binaryClassname::$binaryMethodname()."\n";
+echo $wrongClassname::$binaryMethodname()."\n";
+?>
+===DONE===
+--EXPECTF--
+foo
+foo
+foo
+foo
+Fatal error: Class 'B' not found in %s044.php on line %d
--
To
unsubscribe,
visit: http://www.php.net/unsub.php--
To
unsubscribe, visit: http://www.php.net/unsub.php
This is not really a fix. When we worked on PHP 5 we deliberately
decided to relax on all the weird dynamic constructs which didn't
provide a lot of value for the majority of use-cases. Of course the
Reflection API was going to be the way to do these dynamic things in
future. It would also simplify the engine's code. The reason why those
first constructs work were for BC reasons. We didn't want to break
existing code but wanted to not add on top of this.While it may feel inconsistent I still prefer the existing path. Maybe
for PHP 6 we can even make anE_STRICT
message for the old way which
refers you to the Reflection API?
I think that'd be a bad idea. I don't see a problem with this patch at
all, and why should people use reflection here? As you're always so much
for BC, I find it strange that you're suggesting to remove something
totally harmless and instead want people to force to use the
slow Reflection API which is meant for introspection...
Derick
--
Derick Rethans
http://derickrethans.nl | http://ez.no | http://xdebug.org
Derick Rethans wrote:
This is not really a fix. When we worked on PHP 5 we deliberately
decided to relax on all the weird dynamic constructs which didn't
provide a lot of value for the majority of use-cases. Of course the
Reflection API was going to be the way to do these dynamic things in
future. It would also simplify the engine's code. The reason why those
first constructs work were for BC reasons. We didn't want to break
existing code but wanted to not add on top of this.While it may feel inconsistent I still prefer the existing path. Maybe
for PHP 6 we can even make anE_STRICT
message for the old way which
refers you to the Reflection API?I think that'd be a bad idea. I don't see a problem with this patch at
all, and why should people use reflection here? As you're always so much
for BC, I find it strange that you're suggesting to remove something
totally harmless and instead want people to force to use the
slow Reflection API which is meant for introspection...
I agree its harmless and easy to learn. Moreover I do not see the
benefit of using the Reflection API instead.
@Andi: Could you explain to us why you think that this sort of thing
should best be done through the Reflection API?
regards,
Lukas
I agree with Derick and Lukas. I find the ways this patch proviedes to be
much more "natural" and easy to learn (I personally was in a desparate need
for $classname::everything and also was wondering why it is not implemented,
and then I found the Reflection).
I'm just php developer, and I do not have experiance with other languages,
but still I think the way it is implemented in the patch is the "natural"
way to do it. And if Reflection is slower and meant for introspection why to
use it for this.
Is there any specific consideration for using Reflection for this? Or was
there a discussion about this topic earlier (can somebody point me to it)?
+1 for the patch.
Vesselin Kenashkov
Derick Rethans wrote:
This is not really a fix. When we worked on PHP 5 we deliberately
decided to relax on all the weird dynamic constructs which didn't
provide a lot of value for the majority of use-cases. Of course the
Reflection API was going to be the way to do these dynamic things in
future. It would also simplify the engine's code. The reason why those
first constructs work were for BC reasons. We didn't want to break
existing code but wanted to not add on top of this.While it may feel inconsistent I still prefer the existing path. Maybe
for PHP 6 we can even make anE_STRICT
message for the old way which
refers you to the Reflection API?I think that'd be a bad idea. I don't see a problem with this patch at
all, and why should people use reflection here? As you're always so much
for BC, I find it strange that you're suggesting to remove something
totally harmless and instead want people to force to use the
slow Reflection API which is meant for introspection...I agree its harmless and easy to learn. Moreover I do not see the
benefit of using the Reflection API instead.@Andi: Could you explain to us why you think that this sort of thing
should best be done through the Reflection API?regards,
Lukas
Derick Rethans schrieb:
I think that'd be a bad idea. I don't see a problem with this patch at
all, and why should people use reflection here? As you're always so much
for BC, I find it strange that you're suggesting to remove something
totally harmless and instead want people to force to use the
slow Reflection API which is meant for introspection.
I agree. The Reflection API is the "right tool for the job" when you
are meta-programming (developing tools such as PHPUnit, for instance)
but not when you are programming.
--
Sebastian Bergmann http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
ACK.
David
Am 02.08.2007 um 11:36 schrieb Sebastian Bergmann:
Derick Rethans schrieb:
I think that'd be a bad idea. I don't see a problem with this
patch at
all, and why should people use reflection here? As you're always
so much
for BC, I find it strange that you're suggesting to remove something
totally harmless and instead want people to force to use the
slow Reflection API which is meant for introspection.I agree. The Reflection API is the "right tool for the job" when you
are meta-programming (developing tools such as PHPUnit, for instance)
but not when you are programming.--
Sebastian Bergmann http://sebastian-
bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514
B85B 5D69
Hello Sebastian,
yep, you and Derick are right here. This is definitively a fix that should
go in. Chinstrap just commit the stuff please.
marcus
Thursday, August 2, 2007, 11:36:54 AM, you wrote:
Derick Rethans schrieb:
I think that'd be a bad idea. I don't see a problem with this patch at
all, and why should people use reflection here? As you're always so much
for BC, I find it strange that you're suggesting to remove something
totally harmless and instead want people to force to use the
slow Reflection API which is meant for introspection.
I agree. The Reflection API is the "right tool for the job" when you
are meta-programming (developing tools such as PHPUnit, for instance)
but not when you are programming.
--
Sebastian Bergmann http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867 C514 B85B 5D69
Best regards,
Marcus
Marcus,
It'd be kind if you gave me chance to reply before you tell people to
"just commit stuff".
I'm just about to hop on a plane and will look at the patch again
tomorrow. If people feel so strongly about it and the patch is decent
(doesn't screw up common case and maintainability) I'm OK with it. It's
not a big deal but being a bit more courteous wouldn't hurt you.
Andi
-----Original Message-----
From: Marcus Boerger [mailto:helly@php.net]
Sent: Thursday, August 02, 2007 4:33 AM
To: Sebastian Bergmann
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] Fix inconsistencies in OO callsHello Sebastian,
yep, you and Derick are right here. This is definitively a
fix that should go in. Chinstrap just commit the stuff please.marcus
Thursday, August 2, 2007, 11:36:54 AM, you wrote:
Derick Rethans schrieb:
I think that'd be a bad idea. I don't see a problem with
this patch
at all, and why should people use reflection here? As
you're always
so much for BC, I find it strange that you're suggesting to remove
something totally harmless and instead want people to force to use
the slow Reflection API which is meant for introspection.I agree. The Reflection API is the "right tool for the
job" when you
are meta-programming (developing tools such as PHPUnit, for
instance)
but not when you are programming.--
Sebastian Bergmann
http://sebastian-bergmann.de/
GnuPG Key: 0xB85B5D69 / 27A7 2B14 09E4 98CD 6277 0E5B 6867
C514 B85B
5D69Best regards,
Marcus--
To
unsubscribe, visit: http://www.php.net/unsub.php
I'll just chime in and say that I also find the current
variable-substitution idiom more "natural" than using a Reflection
class to look up a bunch of stuff...
If it's gonna kill youse guys to keep it in there with some kind of
code-maintenance nightmare, fine, kill it.
But if not, having two ways to do the same thing is not necessarily a
Bad Thing, and I think it's a Fine Thing in this case to have both OOP
Reflection and a more "natural" way to do it.
imho
ymmv
etc
--
Some people have a "gift" link here.
Know what I want?
I want you to buy a CD from some indie artist.
http://cdbaby.com/browse/from/lynch
Yeah, I get a buck. So?