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

er, dunno - I picked it up on the internals mailing list I think, you
might wnat to search that.

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

this is intentional, it isn't going to change ... yes it is weird, we
had a thread about this issue before not long ago on this list where someone
thought it was a bug (I concurred until I was corrected).

> 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(),
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.

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