Re: dynamicaly append method to class - workaround for aggregate_methods()
| From: | Karel Kozlik | Date: | Fri, 20 Mar 2009 15:37:10 +0000 |
| Subject: | Re: dynamicaly append method to class - workaround for aggregate_methods() | ||
| References: | 1 2 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-290378@lists.php.net to get a copy of this message | ||
Hello,
thanks for the hint. It looks nice. Where could I learn more about
$class::$method() syntax? I was not successfull when searching in php manual.
Btw. is it an intended behaviour that $class::$method() works in this
way? I mean that I would pressume that method is called in static
context and the $this should not be avaiable in the method than. So I
affraid a bit that the behaviour will be changed in the (near) future.
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?
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{__call() will allow you to do this, although you will need php5.3: <?php class DataLayer_update_attr {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.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 30Any ideas? many thanks, Karel