Re: dynamicaly append method to class - workaround for aggregate_methods()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Karel Kozlik schreef:
>>
>>> 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);

oh yeah d'oh. silly me, that's why I suggested the php5.3+ syntax in the
first place.

> 
>> 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? 

that's what I meant.

> Better doing this I will think how to change the
> whole design, but this is what I wanted to avoid.
>

take a look at interfaces, with the intention that you normalize the method
signatures. additionally take a hard look as to whether you needs so many
'decorator' classes, I can imagine that there will be quite a bit of
code that can be refactored into something more generic.

big job, but it keeps you off the street ;-)

> 
> 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


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux