class myClass { $ myVariable ='myCallback';
function myFunction() {
$body = false;
$callback = $this->myVariable;
function test($handle, $line) {
global $body, $callback;
if ($body) {
call_user_func($callback, $line);
}
if ($line === "\r\n") {
$body = true;
}
return strlen($line);
}
...
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'test');
...
}
}
function myCallback($data) {
print $data;
}
$myCls = new myClass();
$myCls->myFunction();
警告:call_user_func()[function.call-user-func]:第一个参数应该是一个有效的回调!
我的$回调值为空,如何解决此问题? 限制:myCallback功能无法更改!
答案 0 :(得分:10)
重要提示:这仅适用于PHP> = 5.3。 OP不使用PHP 5.3,但我会留下答案,以防有人遇到类似问题并使用PHP 5.3。
$callback
不是全局变量,它在方法范围内是本地变量。来自documentation:
闭包还可以从父作用域继承变量。 必须在函数头中声明任何此类变量。从父作用域继承变量与使用全局变量不同。全局变量存在于全局作用域中,无论执行什么函数,它都是相同的。闭包的父作用域是声明闭包的函数(不一定是从中调用它的函数)。
利用use
(并将函数分配给变量):
$test = function($handle, $line) use ($callback, $body){
if ($body) {
call_user_func($callback, $line);
}
if ($line === "\r\n") {
$body = true;
}
return strlen($line);
};
以后:
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $test);
答案 1 :(得分:2)
除了声明$myVariable
时丢失的关键字之外,这不应该抛出错误,因为test()
函数$body
内部是NULL
除非您定义它在全球范围内。换句话说,永远不应该调用 myCallback 。显然,您确实在全局范围内定义了$body
,并使其成为使用全局变量导致各种意外行为的一个很好的例子。如果你要在全局范围内定义$callback
来保存'myCallback'它应该可以工作,但是你不想要全局变量。
并帮自己一个忙,摆脱方法中的功能:
class myClass {
protected $_myVariable = 'myCallback';
public function myFunction()
{
// calling callback that calls callback (should make you think ;))
// that would be your curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'test');
echo call_user_func_array(
array($this, '_test'),
array('body', 'foo', 'bar'));
}
protected function _test($body, $handle, $line)
{
if ($body) {
call_user_func($this->_myVariable, $line);
}
if ($line === "\r\n") {
$body = true;
}
return strlen($line);
}
}
test()
函数现在是您班级中的一种方法。与将代码流放入方法中的某个函数相比,这更清晰,更易于维护。请注意,我传入$body
作为第一个参数。我不知道cURL如何接受回调或它传递给它们的内容。如果您无法将$body
作为第一个参数,请将其作为类成员检查其状态为$this->body
而不是as now shown by Philippe below)
答案 2 :(得分:2)
只为了另一个的乐趣......(虽未测试)。
class myClass
{
protected $callback = 'myCallback';
protected $body = false;
public function myFunction()
{
...
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, 'test'));
...
}
public function test($handle, $line)
{
if ($this->body) {
call_user_func($this->callback, $line);
}
if ($line === "\r\n") {
$body = true;
}
return strlen($line);
}
}
function myCallback($data) {
print $data;
}
$myCls = new myClass();
$myCls->myFunction();