When using PHP functions such as array_map, usort or preg_replace_callback, you are forced to pass in a single-parameter callback function, making it impossible to send additional context information to the callback. But it ain't necessarily so.
Function objects, aka Functors, are here to help. The idea is to create a small object that holds the additional context for you, and that will call your callback on your behalf, provided you can convince the PHP function to call a method on this object.
Here's how to do it:
<?php
/**
* A function object class to allow callbacks with arbitrary parameters.
*/
class Functor {
function __construct($callback, $args) {
$this->callback = $callback;
$this->args = $args;
}
function callback() {
$args = array_merge(func_get_args(), $this->args);
return call_user_func_array($this->callback, $args);
}
static function create_functor($callback) {
$args = func_get_args();
array_shift($args);
return array(new Functor($callback, $args), 'callback');
}
var $callback;
var $args;
};
?>
Here's an example of using the functor, in the realm of Drupal filters:
<?php
/**
* Implementation of hook_filter().
*/
function myfilter_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'process':
return preg_replace_callback(MYFILTER_REGEX, Functor::create_functor('myfilter_process', $format), $text);
}
}
function myfilter_process($matches, $format) {
$text = $matches[0];
....
return $text;
}
?>
That's it! Happy coding.
Comments
Just read your article on Drupal planet. This is exactly what I was looking for recently. Thank you so much! :)