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:
是否有可能在PHP中加载一个函数,比如从外部文件中加入一个类。我正在尝试为辅助函数创建一个加载器,以便我可以调用:
$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
谢谢你的帮助
3 个解决方案
#1
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.
抛开意见,这是一个很好的OOP设计。即使使用当前版本的PHP,它也有可能,尽管不像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);
}
}
#2
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).
好的,1,我同意这是不礼貌的。另外,在5.3中,您可以使用带有__call魔术字的新闭包语法将运算符用作函数(JS样式)。
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.
现在,如果我们想提供一种方法,我可以考虑使用create_fnuction,与__call魔法混合使用。
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.
基本上,你使用正则表达式模式将函数转换为兼容的字符串,并将minmin作为私有成员。而不是使用__call方法来获取它们。我正在做一个小型演示。
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:
好的,这是班级。我从几周前看到的类中获得了灵感,它使用闭包来实现JS风格的对象:
/**
* 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 <arieh.glazer@gmail.com>
* @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:
限制 - 第1,源不能有任何php标签。 2,功能永远是公开的。 3-我们只能模仿$ this。我做的是作为第一个参数$ this传递,第二个是参数数组(这是第四个限制)。此外,您将无法从班级内访问非公开成员和方法。源文件的示例:
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
对我来说这是一个有趣的练习,但总的来说这是一个糟糕的练习
#3
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.
在这一点上值得注意的是,一个神的物体几乎是不变的反模式。如果您需要全局这些函数,请使用bootstrapping include技术然后将其置于全局范围内。如果需要传递该数据,则根据需要将其传递给函数,或将其存储在数据库中并在其他地方检索。
I know that god object really looks like a good idea, but I promise you it will make things a mess later on.
我知道上帝对象看起来确实是个好主意,但我保证你以后会把事情搞得一团糟。
#1
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.
抛开意见,这是一个很好的OOP设计。即使使用当前版本的PHP,它也有可能,尽管不像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);
}
}
#2
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).
好的,1,我同意这是不礼貌的。另外,在5.3中,您可以使用带有__call魔术字的新闭包语法将运算符用作函数(JS样式)。
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.
现在,如果我们想提供一种方法,我可以考虑使用create_fnuction,与__call魔法混合使用。
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.
基本上,你使用正则表达式模式将函数转换为兼容的字符串,并将minmin作为私有成员。而不是使用__call方法来获取它们。我正在做一个小型演示。
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:
好的,这是班级。我从几周前看到的类中获得了灵感,它使用闭包来实现JS风格的对象:
/**
* 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 <arieh.glazer@gmail.com>
* @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:
限制 - 第1,源不能有任何php标签。 2,功能永远是公开的。 3-我们只能模仿$ this。我做的是作为第一个参数$ this传递,第二个是参数数组(这是第四个限制)。此外,您将无法从班级内访问非公开成员和方法。源文件的示例:
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
对我来说这是一个有趣的练习,但总的来说这是一个糟糕的练习
#3
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.
在这一点上值得注意的是,一个神的物体几乎是不变的反模式。如果您需要全局这些函数,请使用bootstrapping include技术然后将其置于全局范围内。如果需要传递该数据,则根据需要将其传递给函数,或将其存储在数据库中并在其他地方检索。
I know that god object really looks like a good idea, but I promise you it will make things a mess later on.
我知道上帝对象看起来确实是个好主意,但我保证你以后会把事情搞得一团糟。