无法从类内部调用存储为字符串的函数

时间:2011-02-07 13:37:56

标签: php event-handling singleton

编辑:对不起,伙计,这是一个错字=(

我因为浪费你的时间而感到尴尬。我打开这个帖子,希望有人可能会发现讨论的信息有用。

为了进一步澄清,下面的代码将按预期工作,我在代码中输错了'classHandler',这就是PHP无法找到它的原因。

此外,某些评论者注意到的语法错误已得到纠正

我觉得有必要总结一下这个帖子的讨论:


@wimvds建议使用继承,我的实现不是一个好习惯。

@Victor Nicollet不同意说扩展现有实例的行为是1.不可能和2.糟糕的设计

@ircmaxell补充说:记住,你应该总是喜欢构图而不是继承。这不是意大利面条代码,它是实现精简通知系统的一种非常标准的方法(你可以构建一个完整的观察者或中介模式,但对于非常简单的任务,这可能会更好,因为它更容易维护)。

@Victor要求返回此错误的最小一个文件示例。这就是帮我解决问题的原因。当我尝试使用示例文件时,它完美地让我相信其他事情确实是错误的。

@Shakti Singh建议尝试call_user_func( array( $this, $this->handler ), $var);

@Victor Nicollet回应说这将尝试调用成员函数$ this-> classHandler(可能不存在)而不是全局classHandler

@abesto给了它一个镜头,最终得到了一个非常类似于我自己的实现,它没有我的错字。

@Victor Nicollet通过声称需要在调用之前定义classHandler来回答。

@Blizz回应称PHP首先解析类和函数,然后解析常规代码。


MyClass.php (单身)

public $handler;

public function myMethod()
{
    $var = "test";
    call_user_func( $this->handler, $var ); 
    // PHP Warning: First argument is expected to be a valid callback
}

的script.php

$myClass = new MyClass;
$myClass->handler = "classHandler";
$myClass->myMethod();

function classHandler( $var )
{
    echo $var;
}

如果这不正确,在php中调用处理程序/事件处理程序的常用方法是什么?

请注意,这是实际脚本的简化版

3 个答案:

答案 0 :(得分:2)

你必须打这样的话

call_user_func( array( $this, $this->handler ), $var);

答案 1 :(得分:0)

再次阅读Script.php代码。它正在做的是:

  1. 实例化MyClass(我假设你忘了这里的new)。
  2. 将处理程序定义为classHandler
  3. 运行myMethod(),尝试拨打classHandler
  4. 定义classHandler
  5. 显然,如果你在运行4之前运行3,它就不会起作用。您必须首先定义该函数,然后然后运行可能要调用它的任何代码。

    在更大的方案中,我怀疑没有像Script.php这样的文件,而是文件 A 定义了类,文件 B 实例化了类并运行myMethod和文件 C 定义classHandler。在这种情况下,您需要确保在 B 运行之前加载文件 C

答案 2 :(得分:0)

首先:如果将函数存储为字符串意味着实际的实现是在字符串中,那么这是不好的做法。你没有必要这样做才能得到你想要的东西。

function afun($param) {}
class BClass { function bfun($param) {} }

call_user_func('afun', 'param');  // Calls function afun

$binstance = new BClass();
call_user_func(array($binstance, 'bfun'), 'param'); // Calls bfun on binstance 


// Update according to comment
class CClass {
    private $handler;

    public function __construct($handler) { $this->handler = $handler; }

    public foo() {
      // do stuff
      call_user_func($this->handler, 'param');
    }
}
$cinstance = new CClass('afun');
$cinstance->foo();