Hi,
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:
I believe it would be nice to be able to dynamically reference static
members, constants, and methods.
Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname, 'getThat'));
In other words:
class A {
public static $foo = 'value1';
const gee = 'value2';
public static function bar() { return 'value3'; }
// old way:
public static function getFoo() { return self::$foo; }
public static function getGee() { return self::gee; }
}
$classname = 'A';
echo $classname::$foo; // value1
echo $classname::gee; // value2
echo $classname::bar(); // value3
// --- instead of: ---
$classname = 'A';
echo call_user_func(array($classname, 'getFoo')); // value1
echo call_user_func(array($classname, 'getGee')); // value2
echo call_user_func(array($classname, 'bar')); // value3
which is quite slow.
Please take a look at the patch[1] I made for it. Comments would be
appreciated!
Regards,
1: http://patches.colder.ch/Zend/dynamic-static-calls.patch?markup
--
Etienne Kneuss
http://www.colder.ch
colder@php.net
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
+1
Nice to be able to do this directly without resorting to call_user_func()
.
Edom
Etienne Kneuss wrote:
Hi,
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:I believe it would be nice to be able to dynamically reference static
members, constants, and methods.Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname,
'getThat'));In other words:
class A {
public static $foo = 'value1';
const gee = 'value2';
public static function bar() { return 'value3'; }// old way: public static function getFoo() { return self::$foo; } public static function getGee() { return self::gee; }
}
$classname = 'A';
echo $classname::$foo; // value1
echo $classname::gee; // value2
echo $classname::bar(); // value3// --- instead of: ---
$classname = 'A';
echo call_user_func(array($classname, 'getFoo')); // value1
echo call_user_func(array($classname, 'getGee')); // value2
echo call_user_func(array($classname, 'bar')); // value3which is quite slow.
Please take a look at the patch[1] I made for it. Comments would be
appreciated!Regards,
1: http://patches.colder.ch/Zend/dynamic-static-calls.patch?markup
Hi,
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:I believe it would be nice to be able to dynamically reference static
members, constants, and methods.Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname, 'getThat'));In other words:
I'm +0 if it's for HEAD only.
Also I can see only two tests at the moment, we'll need MUCH more.
There are so much combinations to test: unicode & binary strings, numbers, arrays, objects, booleans etc. etc.
--
Wbr,
Antony Dovgal
Hi,
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:I believe it would be nice to be able to dynamically reference static
members, constants, and methods.Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname, 'getThat'));In other words:
I'm +0 if it's for HEAD only.
Also I can see only two tests at the moment, we'll need MUCH more.
There are so much combinations to test: unicode & binary strings, numbers, arrays, objects, booleans etc. etc.--
Wbr,
Antony Dovgal
There are actually 3 tests....
Tijnema
+1
Hi,
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:I believe it would be nice to be able to dynamically reference static
members, constants, and methods.Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname, 'getThat'));In other words:
I'm +0 if it's for HEAD only.
Also I can see only two tests at the moment, we'll need MUCH more.
There are so much combinations to test: unicode & binary strings, numbers, arrays, objects, booleans etc. etc.--
Wbr,
Antony DovgalThere are actually 3 tests....
Tijnema
--
--
David Coallier,
Founder & Software Architect,
Agora Production (http://agoraproduction.com)
51.42.06.70.18
Hi,
In this way, classes can be considered as polymorphism, just like objects.
So is it OK to allow abstract static function in abstract class to support
this feature directory? Currently it is forbidden in HEAD, only interfaces
can have static function.
Thanks
2007/4/27, Etienne Kneuss colder@php.net:
Hi,
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:I believe it would be nice to be able to dynamically reference static
members, constants, and methods.Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname,
'getThat'));In other words:
class A {
public static $foo = 'value1';
const gee = 'value2';
public static function bar() { return 'value3'; }// old way: public static function getFoo() { return self::$foo; } public static function getGee() { return self::gee; }
}
$classname = 'A';
echo $classname::$foo; // value1
echo $classname::gee; // value2
echo $classname::bar(); // value3// --- instead of: ---
$classname = 'A';
echo call_user_func(array($classname, 'getFoo')); // value1
echo call_user_func(array($classname, 'getGee')); // value2
echo call_user_func(array($classname, 'bar')); // value3which is quite slow.
Please take a look at the patch[1] I made for it. Comments would be
appreciated!Regards,
1: http://patches.colder.ch/Zend/dynamic-static-calls.patch?markup
--
Etienne Kneuss
http://www.colder.ch
colder@php.netMen never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- PascalIndex: Zend/zend_language_parser.y
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.179
diff -u -r1.179 zend_language_parser.y
--- Zend/zend_language_parser.y 4 Mar 2007 16:25:57 -0000 1.179
+++ Zend/zend_language_parser.y 6 Mar 2007 14:43:49 -0000
@@ -642,6 +642,12 @@
| fully_qualified_class_nameT_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);}
| 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);}
| variable_without_objects '(' {
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); }
function_call_parameter_list ')'
{ zend_do_end_function_call(&$1, &$$, &$4, 0, 1
TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
@@ -795,6 +801,11 @@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); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
;@@ -930,6 +941,7 @@
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 6 Mar 2007 14:43:49 -0000
@@ -0,0 +1,14 @@
+--TEST--
+Dynamic access of static members
+--FILE--
+<?php
+class A {
- public static $b = 'foo';
+}
+$classname = 'A';
+echo $classname::$b;
+?>
+===DONE===
+--EXPECT--
+foo
+===DONE===
Index: tests/lang/042.phpt
===================================================================
RCS file: tests/lang/042.phpt
diff -N tests/lang/042.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/042.phpt 6 Mar 2007 14:43:49 -0000
@@ -0,0 +1,14 @@
+--TEST--
+Dynamic access of constants
+--FILE--
+<?php
+class A {- const B = 'foo';
+}
+$classname = 'A';
+echo $classname::B;
+?>
+===DONE===
+--EXPECT--
+foo
+===DONE===
Index: tests/lang/043.phpt
===================================================================
RCS file: tests/lang/043.phpt
diff -N tests/lang/043.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/lang/043.phpt 6 Mar 2007 14:43:49 -0000
@@ -0,0 +1,14 @@
+--TEST--
+Dynamic call for static methods
+--FILE--
+<?php
+class A {- static function foo() { return 'bar'; }
+}
+$classname = 'A';
+echo $classname::foo();
+?>
+===DONE===
+--EXPECT--
+bar
+===DONE===--
--
Best regards,
Jingcheng Zhang
Room 304, Dormitory 26 of Yuquan Campus, Zhejiang University
P.R.China
I've already proposed that 1-2 months ago, but now seems to be a good
time to discuss new things, so let's try again:I believe it would be nice to be able to dynamically reference static
members, constants, and methods.Currently, there is no way to do that and the only way would be to
create a static method and use call_user_func(array($classname,
'getThat'));
Could you describe a couple of use cases where you would use such things
(i.e. in real world scripts/libraries)?
Stanislav Malyshev, Zend Products Engineer
stas@zend.com http://www.zend.com/
Hi,
Stanislav Malyshev wrote:
Could you describe a couple of use cases where you would use such
things (i.e. in real world scripts/libraries)?
Sure, let's take an example:
You have a library that uses a factory pattern, but you'd like to cache
those already generated objects in a static variable in the class. Now,
this feature is required in many classes and you'd not like to duplicate
too much code, so a solution would be:
class MySuperClass {
private static $_objectsLoaded = array();
public static function factory($pkId, $classname = __CLASS__) {
if(isset($_objectsLoaded[$classname][$pkId])) {
return $_objectsLoaded[$classname][$pkId];
}
$o = new $classname();
//load stuff from the database
$table = $classname::$_table;
$pkField = $classname::$_pkField;
// build query using $table, and $pkField, load stuff into $o, etc..
if(!is_array(self::$_objectsLoaded[$classname])) {
self::$_objectsLoaded[$classname] = array();
}
self::$_objectsLoaded[$classname][$pkId] = $o;
return $o;
}
public static function create($classname = __CLASS__) {
$o = new $classname();
// ...
return $o;
}
}
class MyClass extends MySuperClass {
protected static $_pkField = 'id';
protected static $_table = 'theTable';
public static factory($pkId, $classname = CLASS) {
return parent::factory($pkId,$classname);
}
public static create($classname = __CLASS__) {
return parent::create($classname);
}
// ...
}
There may be some typos in the code above that makes its syntax
incorrect, but the idea is here.
Now, as you can see, because late static binding is not yet implemented
and probably never will be because of the overhead it might introduce,
you've to pass the classname as a parameter and use it to request things
from the child's class, at this point, being able to do that using that
$classname:: shortcut is quite elegant, instead of having to use
overkill call_user_func calls as all those _get*() methods would have to
be redefined in every the child classes.
I wouldn't mind having to use multiple call_user_func calls for that
purpose if I knew it was too hard to implement that $classname:: thing,
but it's so easy that I really believe it's a feature worth having. And
PHP is also about multiple ways of doing something, right ? :)
--
Etienne Kneuss
http://www.colder.ch
colder@php.net
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal