But there still remains two issues:
1. How to pass arguments to method? The number of arguments is different
for each method. So is the only way to construct a string containing the
arguments and use eval()? Or is there an another way?
then use call_user_func() and/or call_user_func_array() inside __call(),
I tryed it, but it unfortunately does not work. In this case the method
is called in static context and the $this is not avaiable in the method.
I tryed both:
call_user_func_array(array($class, $method), $args);
and
call_user_func_array($class."::".$method, $args);
although given the seemingly 'broken' (mho) design and infinite variations that are
possible in terms of method argument invocation you might consider
tackling the whole system from a wider perspective (probably not what you want to
hear I guess)
also see: http://bugs.php.net/bug.php?id=40694
basically the by-ref issue is not, seemingly, really solvable - I'd say using by-ref
in most cases is unwarranted anyway ... but, you may be able to work round it by using
a static variable inconjunction with a, second, retrieval method in the
decorating classes that overcome the requirement for by-ref ... if that makes sense.
Hmmm I am not sure if I understand correctly, but I guess the use of
second, retrieval method will require changes in all methods that use
the by-ref arguments and also at all places where these methods are
called. Am I right? Better doing this I will think how to change the
whole design, but this is what I wanted to avoid.
thanks for your help
K.
looks like you have your work cut out for you!
2. Arguments sometimes need to be passed by reference. It seems that
__call() does not support passing arguments by reference :(. So I have
not idea how workaround it.
thanks,
Karel
Jochem Maas napsal(a):
Karel Kozlik schreef:
Hello list!
I am using in my application dynamic method appending to class with
aggregate_methods() function. But this function is no more aviable in
php5 and runkit extension seems not to be maintained any more. So I
would like to replace it with something more common (__call method or
so).
Just to describe the situation (simplified). There is one common class
containing some common functions:
class DataLayer{
function add_method($method){
aggregate_methods($this, "DataLayer_".$method);
}
function common_funct_foo(){
...
}
function common_funct_bar(){
...
}
}
And there is hundreds of data manipulation methods (defined within
separate classes) which could call common functions. E.g.:
class DataLayer_get_items{
function get_items(){
$this->common_funct_foo();
return something;
}
}
And they could also call other dynamicaly added methods:
class DataLayer_update_attr{
function update_attr(){
$this->get_items();
$this->common_funct_bar();
return;
}
}
All the stuff is used e.g. in this way:
$data = new DataLayer();
$data->add_method('get_items');
$data->add_method('update_attr');
$data->update_attr();
Now the question is whether is it possible to somehow replace
functionality of add_method() without aggregate_methods() or
runkit_class_adopt(). And _WITHOUT_ need to change the hundreds of
DataLayer_* classes. The change should be only in the main DataLayer
class.
I was thinking about __call() method, but I do not know how to deal
with the $this in dynamicaly appended functions. I need somehow make to
$this in these functions reference to instance of DataLayer class.
__call() will allow you to do this, although you will need php5.3:
<?php
class DataLayer_update_attr
{
function update_attr()
{
echo __METHOD__, "\n";
$this->common_funct_bar();
$this->get_items();
return;
}
}
class DataLayer
{
function common_funct_foo() { echo __METHOD__, "\n"; /* ... */ }
function common_funct_bar() { echo __METHOD__, "\n"; /* ... */ }
function __call($method, $args)
{
$class = "DataLayer_{$method}";
echo __METHOD__, " ... trying {$class}::{$method}()\n";
if (!class_exists($class, true)) // trigger autoload
throw new Exception("buddy we don't have a $class, so
$method is not callable");
$class::$method();
}
}
$d = new DataLayer;
$d->update_attr();
?>
----- output ------
[22:11:16] jochem::~/test > ~/src/php5.3-200808312030/sapi/cli/php -n
-f ./class_agg.php
DataLayer::__call ... trying DataLayer_update_attr::update_attr()
DataLayer_update_attr::update_attr
DataLayer::common_funct_bar
DataLayer::__call ... trying DataLayer_get_items::get_items()
Fatal error: Uncaught exception 'Exception' with message 'buddy we
don't have a DataLayer_get_items, so get_items is not
callable' in /Users/jochem/test/class_agg.php:30
Stack trace:
#0 [internal function]: DataLayer->__call('get_items', Array)
#1 /Users/jochem/test/class_agg.php(11): DataLayer->get_items()
#2 /Users/jochem/test/class_agg.php(32):
DataLayer_update_attr->update_attr()
#3 [internal function]: DataLayer->__call('update_attr', Array)
#4 /Users/jochem/test/class_agg.php(37): DataLayer->update_attr()
#5 {main}
thrown in /Users/jochem/test/class_agg.php on line 30
Any ideas?
many thanks,
Karel
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php