0

When I execute following code I am getting this error. Why is that? What is the proper use of callbacks?

CODE (simplified)

class NODE {
  //...some other stuff
  function create($tags, $callback=false) {
    $temp = new NODE();
    //...code and stuff
    if($callback) $callback($temp); //fixed (from !$callback)
    return $this;
  }
}
$document = new NODE();
$document->create("<p>", function($parent) {
$parent->create("<i>");
});

ERROR

Fatal error: Function name must be a string in P:\htdocs\projects\nif\nif.php on line 36
Are
  • 2,160
  • 1
  • 21
  • 31

5 Answers5

3
$document->new NODE();

This is not valid syntax. The accepted format would be:

$document = new NODE();

In addition to this, if you use the unary operator (!) on a false, you get true. If you use it on a Callable, you get false. As such, if (!$callback) $callback() will throw the first error of your script.

As a side note, you are reinventing the wheel. I would strongly recommend you take a look at the DOMDocument family of classes, which are doing exactly what you are currently trying to implement, albeit with fewer callbacks.

Sébastien Renauld
  • 19,203
  • 2
  • 46
  • 66
  • oops, it should be `document = new NODE();`, fixing. – Are May 31 '13 at 23:00
  • Yes, I know `DOMDocument` but i need to write my own library for few purposes. – Are May 31 '13 at 23:06
  • 1
    @AreWojciechowski: What is your purpose? You are aware that you can extend `DOMDocument`, right? If that doesn't fit the bill, you can also write a `Mediator` or `Adaptor` for it to do what you want to do. – Sébastien Renauld May 31 '13 at 23:07
  • I can't use external libraries or rather - I don't want to. – Are May 31 '13 at 23:09
  • 1
    @AreWojciechowski: Any better reason than "don't want to"? – Sébastien Renauld May 31 '13 at 23:11
  • +1 (and more if I could give it) for just `extend`ing DOMDocument. – Wrikken May 31 '13 at 23:11
  • 'external'? [You have to explicitly disable it during compile time to remove it from PHP](http://www.php.net/manual/en/dom.installation.php). – Wrikken May 31 '13 at 23:14
  • @Wrikken by external I meant "written by me". it's for exercise. – Are May 31 '13 at 23:17
  • Ah well, just make sure your exercise doesn't end up in production is my thought on the matter. At any rate, the comment about the `!` not supposed to be there holds true. – Wrikken May 31 '13 at 23:18
1
if(!$callback) $callback($temp);

should probably be

if($callback) $callback($temp);

And the instanciation:

$document = new NODE();
Antoine
  • 2,785
  • 1
  • 16
  • 23
  • You are right about him having the `if` backwards, you are _wrong_ about having to provide a string rather then a function. – Wrikken May 31 '13 at 23:02
  • 1
    Sorry, had the call_user_func function in mind when doing this. Thanks for pointing this out – Antoine May 31 '13 at 23:07
1
if(!$callback) $callback($temp);

If $callback is false, for sure you won't be able to call it as a callback.

moonwave99
  • 21,957
  • 3
  • 43
  • 64
  • `function create($tags, $callback=false) { ... }` $callback is false by default, if not defined by user. if is anything else - executes. right? (i'm not sure if it's good) – Are May 31 '13 at 23:02
0

My 2c here, type hinting may be good to use here as well.

Ex: function create($tags, callable $callback = function())

Rob W
  • 9,134
  • 1
  • 30
  • 50
-1

To do such a thing in php you should use function pointers and tell php which function to execute. Look at this code.

// This function uses a callback function.
function doIt($callback)
{
    $data = acquireData();
    $callback($data);
}


// This is a sample callback function for doIt().
function myCallback($data)
{
    echo 'Data is: ', $data, "\n";
}


// Call doIt() and pass our sample callback function's name.
doIt('myCallback');  

So as you seen you can only pass the name to the function and you should predefine the function..

Similar question: How do I implement a callback in PHP?

Community
  • 1
  • 1
Miro Markaravanes
  • 3,285
  • 25
  • 32
  • Completely off-topic and dangerous malpractice. By doing this, you are polluting the global namespace and forcing PHP to do a hash lookup on explicit name, something you would not have to do otherwise (passing a `Callable` would be one of them). – Sébastien Renauld May 31 '13 at 23:18
  • @SébastienRenauld I'm just trying to give the OP what he wants. and this is not off-topic. see the comments in the OP and you will see why I posted this answer. and stop down-voting to get your answer up. – Miro Markaravanes May 31 '13 at 23:22
  • His question was about the callback not working, not about creating a **doIt** function. His way of doing it is miles better than yours - he passes a function pointer/`Callable`, you pass a string reference (= significantly more memory, causes two PHP internal lookups, causes a below-the-bonnet `call_user_func` call). ***THIS*** is why you got a downvote - I don't have a care in the world about my answer. What I care about is not having OT (and blatantly incorrect) answers on a question. – Sébastien Renauld May 31 '13 at 23:25
  • And just to add water to the mill, this "method" which you copy-pasted from another question dates back from 12/08, when PHP **4** was the de-facto standard. That version of PHP did not have `Callable`. It's 5 years in the future now, and function pointers can be passed to functions. – Sébastien Renauld May 31 '13 at 23:29
  • @SébastienRenauld mate calm down. I didn't say I wrote the code. Did I? There is no need to "add water to the mill". I just posted my answer. either the best solution or the worst, this is my answer. You could simply comment saying this is not a good way to do it. instead of wowing about this being OT when it's actually A WORKING SOLUTION. – Miro Markaravanes May 31 '13 at 23:33
  • Miro: I said exactly that in my first comment. You're the one who went personal, "mate". I (rightfully) called your method a dangerous malpractice and explained exactly why it was. You immediately went *ad hominem*. – Sébastien Renauld May 31 '13 at 23:34