tags:

views:

597

answers:

3

Is it possible in php to load a function, say from a external file to include in a class. I'm trying to create a loader for helper functions so that I could call:

$registry->helper->load('external_helper_function_file');

after that it should be able call the function in file like this:

$registry->helper->function();

Thanks for any help

A: 

So you want to not just include a file, but include it into an object's scope?

...

I think you're going about this the wrong way. It makes more sense if the registry object has a series of helper members, which have functions of their own. The net result might look something like this:

$registry->aHelper->aFunction();
$registry->aDifferentHelper->aDifferentFunction();

With careful use of {} syntax, you should be able to dynamically add member objects to your god object.

At this point it's worth noting that a god object is almost invariable an anti-pattern. If you need those functions globally, use a bootstrapping include technique and put then in global scope. If you need to pass that data around, then either pass it to functions as required or store it in a database and retrieve it elsewhere.

I know that god object really looks like a good idea, but I promise you it will make things a mess later on.

Kalium
Thanks for the input. These helper functions may increase invariably. So I want them only loaded when needed. It will be great if somebody could point in the right direction. Something like CI helpers
saint
Might I suggest you crack open the CodeIgniter codebase, then? If that's your idea model, then it sounds like a good starting point.
Kalium
A: 

ok, 1st, i agree that this is bad manners. also, in 5.3, you could use the new closure syntax with the __call magic word to use operators as functions (JS style).

now, if we want to supply a way of doing this you way, i can think of using create_fnuction, mixed with the __call magic.

basically, you use a regex pattern to get convert the functions into compatible strings, and put themin a private member. than you use the __call method to fetch them. i'm working on a small demo.

ok, here is the class. i got the inspiration from a class i saw a few weeks ago that used closures to implement JS-style objects:

/**
 * supplies an interface with which you can load external functions into an existing object
 * 
 * the functions supplied to this class will recive the classes referance as a first argument, and as 
 * a second argument they will recive an array of supplied arguments.
 * 
 * @author arieh glazer <[email protected]>
 * @license MIT like 
 */
class Function_Loader{
    /**
     * @param array holder of genarated functions
     * @access protected
     */
    protected $_funcs = array();

    /**
     * loads functions for an external file into the object
     * 
     * a note- the file must not contain php tags.
     * 
     * @param string $source a file's loaction
     * 
     * @access public
     */
    public function load($source){
     $ptrn = '/function[\s]+([a-zA-Z0-9_-]*)[\s]*\((.*)\)[\s]*{([\w\s\D]+)}[\s]*/iU';
     $source = file_get_contents($source);
     preg_match_all($ptrn,$source,$matches);
     $names = $matches[1];
     $vars = $matches[2];
     $funcs = $matches[3];
     for ($i=0,$l=count($names);$i<$l;$i++){
      $this->_funcs[$names[$i]] = create_function($vars[$i],$funcs[$i]);
     }
    }

    public function __call($name,$args){
     if (isset($this->_funcs[$name])) $this->_funcs[$name]($this,$args);
     else throw new Exception("No Such Method $name");
    }
}

limitations- 1st, the source cannot have any php tags. 2nd, functions will always be public. 3rd- we can only mimic $this. what i did was to pass as a 1st argument $this, and the second is the array of arguments (which is a 4th limition). also, you will not be able to access non-public members and methods from within the class. an example for a source file:

function a($self,$arr=array()){
    //assuming the object has a member called str
    echo $self->str;
}

this was a fun exercise for me, but a bad practice all in all

XiroX
+2  A: 

Setting aside opinions it it's good OOP design. It's possible even with current version of PHP, although not as clean, as it can be with PHP5.3.

class Helper {
    /* ... */
    function load($file) {
      include_once($file);
    }
    function __call($functionName, $args) {
       if(function_exists($functionName))  
         return call_user_func_array($functionName, $args);
    }

}
vartec
You might want to use call_user_func_array(), in your example the function would be passed all the arguments in one array argument
Tom Haigh
@tomhaigh: right, corrected.
vartec
Thats exactly what I was looking for
saint