PHP / Scope / Callback

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(); 

Warning: call_user_func () [function.call-user-func]: the first argument is expected to be a valid callback!

My callback value is empty, how can I solve this problem? Limitation: myCallback function cannot be changed!

+4
source share
3 answers

Just for the pleasure of him one more ... (did not check, though).

 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(); 
+2
source

Important: This is only possible in PHP> = 5.3. OP does not use PHP 5.3, but I will leave the answer here if someone has a similar problem and uses PHP 5.3.


$callback not a global variable; it is local in the method scope. From the documentation :

Closing can also inherit variables from the parent scope. Any such variables must be declared in the function header. Inheritance of variables from the parent scope does not match global variables. Global variables exist in a global scope, which is the same no matter what function is performed. The parent region of the closure is the function in which the closure was declared (not necessarily the function from which it was called).

Use use (and assign the function to a variable):

 $test = function($handle, $line) use ($callback, $body){ if ($body) { call_user_func($callback, $line); } if ($line === "\r\n") { $body = true; } return strlen($line); }; 

and later:

 curl_setopt($ch, CURLOPT_WRITEFUNCTION, $test); 
+10
source

Except for the missing keyword when declaring $myVariable , this should not cause an error at all, because inside test() function $body is NULL if you did not define it in the global scope. In other words, your myCallback should never be called. Apparently, you still defined $body in the global scope and made it a great example of why using global variables will lead to all kinds of unexpected behavior. If you defined $callback in the global scope to hold "myCallback", it should work, but you don't want global variables.

And do yourself a favor and get rid of the function in the method:

 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); } } 

The test() function is now a method inside your class. This is much clearer and easier to maintain than pasting code into some function inside a method. Note that I pass $body as the first argument. I don't know how cURL accepts callbacks or what it passes to them. If you cannot make $body first argument, make it a member test to specify $this->body instead ( as shown below by Philippe )

+2
source

All Articles