It just took me a while to really understand the differences between this three. But hopefully (never say never ;-), now i got it.
A callback simple describes, that a function awaits another function as parameter. This functions can be an existing one or a "on the fly created on" with the power of create_function.
A lambda function is a function without a function name. The reference is stored in a variable. You can use this variable to handle it over to methods like usort.
As everybody i will use a sorting lambda function for showing what i mean.
/**
* Returns 0 if strings are equal, -1 if $stringTwo or 1 of $stringOne is greater
*
* @author artodeto.bazzline.net
* @param string $stringOne
* @param string $stringTwo
* @return int $sorter
* @since 2012-02-26
*/
$mySorter = function($stringOne, $stringTwo)
{
$sorter = 0;
$lengthOfStringOne = strlen($stringOne);
$lengthOfStringTwo = strlen($stringTwo);
if ($lengthOfStringOne > $lengthOfStringTwo) {
$sorter = 1;
} elseif ($lengthOfStringOne < $lengthOfStringTwo) {
$sorter = -1;
}
return $sorter;
};
$names = array(
'Brian W. Kernighan',
'Dennis Ritchie'
);
usort($names, $mySorter);
echo xdebug_var_dump($names);
?>
It is also possible to define the $mySorter directly in unsort as second parameter like
usort($names, function($stringOne, $stringTwo { ... });
if you like that.
A closure is a function that surrounds (i do not want to use the word enclose
) the lambda function.
That has the sideeffect that the closure itself conserves their own context. An easy example is a simple logger.
/**
* Closure function for logging. Returns true if message could be stored
* Available types are "info" and "error"
*
* @author artodeto.bazzline.net
* @param string $type
* @return boolean
* @since 2012-02-26
*/
function myClosureLogger($type)
{
return function($message) use ($type)
{
$status = false;
switch ($type) {
case 'info':
$myDatabaseInfoLogTable = new DatabaseInfoLogTable();
$myDatabaseInfoLogTable->setMessage($message);
$myDatabaseInfoLogTable->setTimestamp(mktime());
$status = $myDatabaseInfoLogTable->save();
break;
case 'error':
$myFileErrorLog = new ErrorLog();
$myFileErrorLog->addMessage(mktime() . "\t" . $message);
$status = $myFileErrorLog->save();
break;
}
return $status;
};
}
$infoLogger = myClosureLogger('info');
$errorLogger = myClosureLogger('error');
$infoLogger('This is a info log');
$errorLogger('This is an error log');
?>
The positiv thing about closures is, that the code footprint can be reduced (you even can use closures inside objects - even as static if you do not need to access on the object itself with
$this).
The negativ thing is, that you can not use interfaces which implies a lose of security.