Example of a callback in PHP

I was talking with a friend who does most of his coding in C today and he was mentioning callback functions and said how handy they were. Most definitions on the web seemed pretty vague and most of the code was C code involving pointers. I kinda understood it but was wondering if someone could provide a good example of a callback in PHP.

thanks

The [fphp]xml_set_element_handler[/fphp] function, among others, uses callbacks.

Callbacks work like this:

// 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, "\
";
}


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

http://www.php.net/callback

callbacks are indeed very handy in procedural programming, but in OOP every call is resolved via pointer and callbacks as such do not make much sense.


// procedural version
do_something_if_greater($a, $b, $compareFunc) {
   if($compareFunc($a, $b) > 0) ...
}

// oo version
do_something_if_greater($a, $b) {
   if($a->compare($b) > 0) ...
}

Imho, in the OO version this would couple the compare function to $a…

Here is my version :wink:


if ($comparator->compare($a, $b) > 0) { }

Callbacks are much like Delegates, more than anything else, from an object oriented context. Do a search for the Delegate on Google if you want to learn more :slight_smile:

A good example of callback is preg_replace_callback , atleast one i’ve used for complex regexes for text parsing more than once.

Hi.

The PHP array_map() function is a good one…


$lower = array('marcus', 'lastcraft');
$capitalised = array_map('uc_first', $lower);
print_r($capitalised);

Basically you blast the whole array with a function in one go, avoiding looping through it. A much more declarative style.

You can write your own call back functions, as the function name is usually passed as a string…


function process_text($callback, $text) {
    $replaced = array();
    foreach (split($text) as $word) {
        $replaced[] = $callback($word);
    }
    return implode(' ', $replaced);
}

The OO equvalent is either observer, listener or visitor. The listener…


class XmlListener {
    function openTag($tag, $attributes) { ... }
    function characterData($text) { ... }
    function closeTag($tag) { ... }
}

class XmlParser {
    function parse($xml, $listener) { ... }
}

As the parser reads the text, it sends the results as calls to the listener.

The Observer pattern has a single notify() method rather than a full interface. This is equivalent of the delegate in C# I believe (someone please correct me).

The Visitor pattern involves passing the caller itself in as the listener. Say we are using the parser from an RSS reader…


class RssReader {
    function read($url) {
        $parser = new XmlParser();
        $parser->parse(file($url), $this);
    }

    function openTag(...) { ... }
    function characterData(...) { ... }
    function closeTag(...) { ... }
}

Here it’s especially effective. All the RSS code is in one place, and you don’t need any clumsy iterators to move over the data structure (here, text tokens). The Visitor/Listener is often a very nice replacement for the Iterator pattern. It means the mechanics of iteration can stay in the data structure being traversed.

Other languages have different tricks for this. Ruby/Smalltalk/Perl can pass an anonymous block of code (PHP lambda functions are rubbish by comparison). Java can pass an anonymous inner class to avoid polluting the namespace.

For functional languages, callbacks are the foundation. It’s how you get the code to the data. You will see things like “list comprehensions” (basically generators and transformers) used in the same context. Python has some support for this, but I’m not a Python developer, so hopefully someone else will elaborate.

yours, Marcus

And, may I add, javascript excells in this. Since functions are variables, they can be passed around. Gives you plenty of ammunition to shoot yourself, or tools to write some encredibly beautiful code, depending on your skills.

Yeah, can do nice things with javascript. Even create anonymous objects, with methods


	var a = [3, 4, 5];
	run = function(a, o) { for(i in a) { o.visit(a[i]); } };
	var o = { total: 0, visit: function(v) { this.total += v; } };
	run(a, o);	
	alert(o.total);

Doesn’t look like a Visitor to me. It may be a Builder, though.

Let me try a canonical form for the client code:

$rssreader = new RssReader;
$parser = new XmlParser($rssreader);
$parser->parse(file($url));

Now the parser is the Director and the RssReader the Builder. It’s surprisingly similar to the example on page 97 of GoF, except that the RTFReader in that example is Director, not Builder.

Off Topic:

Regarding functional programming, currying et al, there are some nice examples [url=“http://w3future.com/html/beyondJS/”]here](http://ianhenderson.org/currying_in_javascript.html) as well. JavaScript can be a lot of fun :slight_smile:

Currying in php


function curry($func, $arity) {
	return create_function('', "
		\\$args = func_get_args();
		if(count(\\$args) >= $arity)
			return call_user_func_array('$func', \\$args);
		\\$args = var_export(\\$args, 1);
		return create_function('','
			\\$a = func_get_args();
			\\$z = ' . \\$args . ';
			\\$a = array_merge(\\$z,\\$a);
			return call_user_func_array(\\'$func\\', \\$a);
		');
	");
}

function sum($a, $b) {
	return $a + $b;
}

$sum = curry('sum', 2);
$plus5 = $sum(5);
echo $plus5(10); // 15

$map = curry('array_map', 2);
$toupper = $map('strtoupper');
$ary = array('haskell', 'curry',);
print_r($toupper($ary)); // HASKELL CURRY

:wink:

Hi…

I may have played fast and loose with the term “visitor”, but I think it’s just about OK. I am using it in this sense…

http://www.rubycentral.com/book/lib_patterns.html

OK, that doesn’t explain much, because it just points you at “each”. They had a better article somewhere, but I couldn’t find it.

I am on a bit of “replace iterator with visitor” mission at the moment at work, so this is on my brain right now.

Except that I wasn’t even thinking of building anything. I was thinking that the RSS reader would output, say HTML, as the events came in. I didn’t even think of building up the document internally. Goes to show how even the simplest snippet of code can be interpreted completely differently without sufficient context. I should have filled out the other methods.

But then, patterns are fuzzy things best deployed subconsciously I think.

yours, Marcus

I’ve never written a line of Ruby code, but I would venture to say that mixins are the Ruby equivalent of Visitor.

Visitor allows you to add new operations to a class without putting them in the class itself.

It’s “building” on the output. I admit that’s far-fetched, but it may be less far-fetched than calling it Visitor.

Yes and no. I sometimes need to think consciously about them to learn. I keep re-reading GoF and learning something new every time.

Doesn’t look like a Visitor to me.

Looks like a Visitor to me though; It’s the RssReader it’s self that’s acting as the Visitor in this case no?

Hi…

I agree for learning, do it consciously. Once absorbed, I don’t think about them too much at the text editor.

Ruby Mixins are the metaclass stuff. It’s actually the ruby block that’s replacing the visitor…


class IterableFromWithin
    def each()
        names.sort.each { |name|
            yield(name)
        }
    end

    def names
        return ['Marcus', 'Dagfinn']
    end
end

# Pass callback as a block.
IterableFromWithin.new.each { |item| print 'Hello ' + item }

yours, Marcus

IMHO it’s not a Visitor unless it

  • behaves differently depending on what kind of object it visits, and
  • the visited object has an accept() or similarly generic method to allow the Visitor to replace any method that might have been defined in the visited class.

I don’t see that in any of the examples here.

The Visitor pattern is apparently not necessary in Ruby, so I wouldn’t expect Ruby experts to explain it well.

Hi…

It could, but my example was lousy. How about painting a list…


class ListPainter {
    function paint($list) {
        $list->write($this);
    }

    function setBorder($size) { ... }
    function paintTitle($title) { ... }
    function start() { ... }
    function paintItem($item) { ... }
    function finish() { ... }
}

Some examples…


$painter = new PdfListPainter();
$painter->paint($simple_list_with_no_title);
$painter->paint($fancy_nested_list);

The single accept() method is C++ specific, and there the function overloading is used to dispatch. The above uses a second callback instead. I would say that as long as there is a negotiation between the two tightly coupled objects to decide the actual code block to run, then it’s pretty visitorish. Otherwise the Visitor pattern isn’t really a pattern, it’s more of an implementation.

I do agree that I have stretched it as much as the pragmatic programmers have stretched it. I kind of hope the “Prags” win, though. I find the GOF explanation is truly horrible.

yours, Marcus

Very nifty!