【问题标题】:Php (eval vs call_user_func vs variable functions ...)Php(eval vs call_user_func vs 变量函数...)
【发布时间】:2011-06-21 11:26:16
【问题描述】:

尽管有一些关于这个问题的讨论,但我想通过某些示例来检查什么是最好的方法。
我没有使用现有的解决方案,而是创建了自己的持久层(像许多人一样) 所以我的方法在这里也有问题。

对于 db 中的每个表,我都有具有适当的 getter 和 setter 以及一些强制方法的模型类。我还只创建了一个通用 DAO 类来处理所有类型的模型对象。
因此,例如,为了保存任何模型对象,我实例化了 genericDAO 类并调用我将模型对象作为属性传递的保存方法。 问题是,在运行时 genericDAO 类不知道它获取的模型对象以及其中存在哪些方法(getter 和 setter),因此我需要调用强制模型类方法,将属性列表检索为多个字符串数组。
例如,每个属性都有数组(table_column_name,attribute_name,is_string)。

当我调用保存函数时,它看起来像这样:

public function save(&$VO) {  
$paramArray = $VO->getParamArray();//get array of attributes
$paramIdArray = $paramArray[0];  //first attribute is always id
/*create and execute getId() and store value into $void to check if it's save or update*/
eval('$voId = $VO->get'.ucfirst($paramIdArray[1]).'();');  
...

目前我正在使用 eval 来执行这些方法,但众所周知 eval 非常慢。
我正在考虑将其更改为 call_user_func 方法
比如:

$voId = call_user_func(array($VO, 'get'.ucfirst($paramIdArray[1])));

但也有其他解决方案。我也许可以使用这样的东西

$method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->$method();
否则
$method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->{$method}();

最好的方法是什么?

【问题讨论】:

    标签: php


    【解决方案1】:

    我通常会使用:

    $method = 'get'.ucfirst($attribute);
    if(method_exists($obj, $method){
      $obj->$method();
    } 
    

    但除非有很好的理由,否则我只会从 getParamArray 返回一个 key => value 数组。并对其进行操作,而不是使用 getter...

    【讨论】:

    • 是的,如果避免使用 getter 可能会更快......直到他们创建私有访问修饰符:)
    【解决方案2】:

    首先,没有必要像你一样传递引用。您应该give this a read 尝试了解 PHP 如何处理对象引用。

    所以public function save(&$VO) { 应该变成public function save($VO) {

    其次,没有必要使用eval(事实上,由于速度、可调试性等原因,最好不要使用)。您不能像动态调用一样对 eval 调用进行堆栈跟踪。

    第三,call_user_func 几乎没用,因为 PHP 支持动态变量函数。而不是call_user_func(array($obj, $method), $arg1),只需调用$obj->$foo($arg1)call_user_func_array 函数仍然很有用,因为它支持可变长度参数并支持传递引用。

    所以,最终,我会建议:

    $method = 'get' . ucfirst($paramIdArray[1]);
    $voId = $VO->$method();
    

    请注意,无需调用method_exists,因为由于__get 魔术方法支持,它可能是可调用的并且不存在...

    【讨论】:

    • 我认为 call_user_func() 仍然是调用存储在对象变量中的匿名函数的唯一方法:$o->f = function() {}; 尝试执行 $o->f() 将导致 $o doesn't hav a method named 'f' 警告。
    • @Mchl: $c = $o->f; $c(); 会起作用。或者你可以实现一个__call 魔术方法来为你做这件事。但是您没有必须使用call_user_func。这就是我想说的重点。它没有做任何你用母语做不到的事情......它可能更容易做和阅读,但它没有做任何特别的事情......
    • 啊,是的。忘了$c = $o->f; $c();,你说得对。
    • @ircmaxell 感谢您的建议,但我决定通过引用传递的原因是因为保存后我可以从数据库中检索 ID 并在对象中设置 ID。这样我就可以在其余代码中重用该对象。
    • @aleksandar:默认情况下,对象是通过引用传递的……只要是对象,就没有理由使用&运算符……
    猜你喜欢
    • 2011-06-30
    • 2021-03-01
    • 2013-03-09
    • 2011-05-20
    • 2020-10-18
    • 2014-08-08
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多