Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Function Handling Functions : create_function

create_function

Create an anonymous (lambda-style) function (PHP 4 >= 4.0.1, PHP 5)
string create_function ( string args, string code )

Creates an anonymous function from the parameters passed, and returns a unique name for it.

Parameters

Usually these parameters will be passed as single quote delimited strings. The reason for using single quoted strings, is to protect the variable names from parsing, otherwise, if you use double quotes there will be a need to escape the variable names, e.g. \$avar.

args

The function arguments.

code

The function code.

Return Values

Returns a unique function name as a string, or FALSE on error.

Examples

Example755. Creating an anonymous function with create_function()

You can use this function, to (for example) create a function from information gathered at run time:

<?php
$newfunc
= create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo
"New anonymous function: $newfunc\n";
echo
$newfunc(2, M_E) . "\n";
// outputs
// New anonymous function: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
?>


Or, perhaps to have general handler function that can apply a set of operations to a list of parameters:

Example756. Making a general processing function with create_function()

<?php
function process($var1, $var2, $farr)
{
foreach (
$farr as $f) {
echo
$f($var1, $var2) . "\n";
}
}

// create a bunch of math functions
$f1 = 'if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;}';
$f2 = "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);";
$f3 = 'if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; }';
$farr = array(
create_function('$x,$y', 'return "some trig: ".(sin($x) + $x*cos($y));'),
create_function('$x,$y', 'return "a hypotenuse: ".sqrt($x*$x + $y*$y);'),
create_function('$a,$b', $f1),
create_function('$a,$b', $f2),
create_function('$a,$b', $f3)
);

echo
"\nUsing the first array of anonymous functions\n";
echo
"parameters: 2.3445, M_PI\n";
process(2.3445, M_PI, $farr);

// now make a bunch of string processing functions
$garr = array(
create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
'and \"$b\"\n** Look the same to me! (looking at the first 3 chars)";'),
create_function('$a,$b', '; return "CRCs: " . crc32($a) . " , ".crc32(b);'),
create_function('$a,$b', '; return "similar(a,b) = " . similar_text($a, $b, &$p) . "($p%)";')
);
echo
"\nUsing the second array of anonymous functions\n";
process("Twas brilling and the slithy toves", "Twas the night", $garr);
?>

The above example will output:

Using the first array of anonymous functions
parameters: 2.3445, M_PI
some trig: -1.6291725057799
a hypotenuse: 3.9199852871011
b*a^2 = 4.8103313314525
min(b^2+a, a^2,b) = 8.6382729035898
ln(a/b) = 0.27122299212594

Using the second array of anonymous functions
** "Twas the night" and "Twas brilling and the slithy toves"
** Look the same to me! (looking at the first 3 chars)
CRCs: -725381282 , 1908338681
similar(a,b) = 11(45.833333333333%)


But perhaps the most common use for of lambda-style (anonymous) functions is to create callback functions, for example when using array_walk() or usort()

Example757.Using anonymous functions as callback functions

<?php
$av
= array("the ", "a ", "that ", "this ");
array_walk($av, create_function('&$v,$k', '$v = $v . "mango";'));
print_r($av);
?>

The above example will output:

Array
(
[0] => the mango
[1] => a mango
[2] => that mango
[3] => this mango
)

an array of strings ordered from shorter to longer

<?php

$sv
= array("small", "larger", "a big string", "it is a string thing");
print_r($sv);

?>

The above example will output:

Array
(
[0] => small
[1] => larger
[2] => a big string
[3] => it is a string thing
)

sort it from longer to shorter

<?php

usort
($sv, create_function('$a,$b','return strlen($b) - strlen($a);'));
print_r($sv);

?>

The above example will output:

Array
(
[0] => it is a string thing
[1] => a big string
[2] => larger
[3] => small
)


Related Examples ( Source code ) » create_php


Code Examples / Notes » create_php

listes

[Editor's note: Only regular variables are serialized (scalars, arrays, objects), and as lambda functions are not stored as any of those types, it is not saved during session serialization.]
Warning, it seems that you can't store such lambda functions in Sessions, because only the function's name will be stored, not the function itself.
So don't save the function but only it's code and call create_function each time the script is called.


endofyourself

You really should avoid using this as well as you should avoid using eval(). Not only will there be a performance decrease but can it lead to obfuscation and bad coding habits. There is almost always an alternative solution to self modifying code.

db on music_ml

What I posted above is logical because anonymous functions don't inherit the method scope. You'll have to do this:
<?php
class AnyClass {

var $classVar = 'some regular expression pattern';
function classMethod() {
  $_anonymFunc = create_function( '$arg1, $arg2', 'if ( eregi($arg2, $arg1) ) { return true; } else { return false; } ' );
  $willWork = $_anonymFunc('some string', $classVar);

}
}
?>


nospam

Sometimes it may be useful to create functions in a dynamic environment
(f. e. in a daemon-like php script).
Normally declaring a function must be done once, which results in the problem,
that in this special case modifying a function wouldn't have an effect until the script is reloaded.
Maybe this code snipplet is useful 4 u.
File: "functions.inc"
<?php
function test($str) {
   echo $str;
}
?>
Dynamic FunctionHandler:
<?
$FileName = "functions.inc";
$FileHandle = fopen($FileName,"r");
$FileContent = fread($FileHandle,filesize($FileName));
fclose($FileHandle);
preg_match_all("#function\ ?([a-zA-Z0-9-_]*)\ ?\((.*?)\)\ ?\{(.*?)\}#mixse",$FileContent,$Matches);
if ( is_array($Matches) && isset($Matches[0]) && count($Matches[0]) > 0  ) {
foreach ( $Matches[0] as $key=>$val ) {
       $$Matches[1][$key] = create_function($Matches[2][$key],$Matches[3][$key]);
   }
}
?>
The Test:
<?php echo $test("test"); ?>
.. will echo "test";
Hans Kuhlen


info

Note that using __FUNCTION__ in a an anonymous function, will always result '__lambda_func'.
<?php
$fn = create_function('', 'echo __FUNCTION__;');
$fn();
// Result: __lambda_func
echo $fn;
// Result: ºlambda_2 (the actual first character cannot be displayed)
?>
This means that a anonymous function can't be used recursively. The following code (recursively counting to 10) results in an error:
<?php
$fn2 = create_function('$a', 'echo $a; if ($a < 10) call_user_func(__FUNCTION__, $a++);');
$fn2(1);
// Warning: call_user_func(__lambda_func) [function.call-user-func]: First argument is expected to be a valid callback in T:/test/test.php(21) : runtime-created function on line 1
?>


magicaltux

neo at gothic-chat d0t de wrote :
Beware of memory-leaks, the garbage-collection seems to 'oversee' dynamically created functions!
Not really...
In fact, PHP can not "unassign" functions. So if you create a function, it won't be deleted until the end of the script, even if you unset the variable containing its name.
If you need to change a part of a function everytime you run a loop, think of a way to make a more general function or try using eval :) (functions are made to be re-used. If you need to run your own piece of code once, eval is much better).


a dot steenveld

It is possible to use this call to implement continuations but you need a small workaround for a nagging feature of create_function(). The result of this function does start with a null character which might result in loosing the name of your function altogether!. (See also bug report #40160)
Here is a bit of code to play with. The result should be 'f(2, 2) = 6'
<?php
/* continuations in php.
  vim:nu
  Code inspired by http://www.ps.uni-sb.de/~duchier/python/continuations.html
*/
function writeln($s) { echo "$s\n"; }
function lambda0 ($args, $code)
{ return substr(create_function ($args, $code), 1);
}
function L ($l)
{ if (strncmp($l, 'lambda_', 7) === 0) return "\0$l";
 else return $l;
}

function mul ($x, $y, $c) { $f = L($c); $f($x*$y); }
function add ($x, $y, $c) { $f = L($c); $f($x+$y); }
function mal ($x, $y, $c) { mul(2, $x, lambda0 ('$v', "add(\$v, $y, $c);")); }
function f($x, $y)
{ mal($x, $y, lambda0 ('$v', "writeln(\"f($x, $y) = \$v\");"));
}
f(2, 2);
?>


kkaiser

In the process of migrating a PHP4 codebase to PHP5, I ran into a peculiar problem. In the library, every class was derived from a generic class called 'class_container'. 'class_container' contained an array called runtime_functions and a method called class_function that was as follows:
function class_function($name,$params,$code) {
 $this->runtime_functions[$name] = create_function($params,$code);
}
In a subclass of class_container, there was a function that utilized class_function() to store some custom lambda functions that were self-referential:
function myfunc($name,$code) {
 $this->class_function($name,'$theobj','$this=&$theobj;'.$code);
}
In PHP4, this worked just fine. The idea was to write blocks of code at the subclass level, such as "echo $this->id;", then simply $MYOBJ->myfunc("go","echo $this->id;"); and later call it like $MYOBJ->runtime_functions["go"]();
It essentially worked exactly like binding anonymous functions to objects in Javascript.
Note how the "$this" keyword had to be manually redefined for the $code block to work.
In PHP5, however, you can't redeclare $this without getting a fatal error, so the code had to be updated to:
function myfunc($name,$code) {
 $this->class_function($name,'$this',$code);
}
Apparently create_function() allows you to set $this via a function argument, allowing you to bind anonymous functions to instantiated objects. Thought it might be useful to somebody.


colin dot mckinnon

In response to koyama at hoge dot org (14-Dec-2000):
This does NOT create a new method - try adding this at the end:
if (function_exists($h->lamda)) {
  print "Its a function\n";
} else {
  print "No it isnt";
}
It creates a function which $h->lamda points to.
Under PHP4 you could simply add an argument $this which meant it *behaved* like a method (though it existed in global scope) but with PHP5, you can't have a variable named $this in a function (which is rather irksome).
(and methinks the ant-bot challenge is taking the mickey - min(three, four)?  !).


phlyst

In reply to info at adaniels dot nl:
You may not be able to use __FUNCTION__ in a lambda (thanks for pointing it out; I was having that problem just now), but you can use $GLOBALS to work around it if you're assigning the function to a variable. I reimplemented array_walk_recursive() in PHP4 like this:
<?php
$array_walk_recursive = create_function('&$array, $callback',
   'foreach($array as $element) {
       if(is_array($element)) {
           $funky = $GLOBALS["array_walk_recursive"];
           $funky($element, $callback);
       }
       else {
           $callback($element);
       }
   }');
?>


josh j

In regards to the recursion issue by info at adaniels dot nl
Anon function recursion by referencing the function variable in the correct scope.
<?php
$fn2 = create_function('$a', 'echo $a; if ($a < 10) call_user_func($GLOBALS["fn2"], ++$a);');
$fn2(1);
?>


boards

If you were checking to see if a function is made properly, this would be a better way of checking:
<?php
$fnc = @create_function('$arg1,$arg2,$arg3', 'return true;');
# make that function whatever you want
if (empty($fnc)) {
 die('Could not create function $fnc.');
}
# although, the follow will NOT work
if (empty(create_function('$arg', 'return $arg;'))) {
 die('Could not create anonymous function.');
}
# you would get an error regarding not being able to use a
# return value in writeable context (i.e. a return value is
# a const in C, and the function empty() doesn't use a
# const void* parameter
?>


koyama

How do you use function which is created by create_function() as class method?
<?php
class Hoge {
 var $lamda;
 function set($lamda) {
   $this->lamda = $lamda;
 }
 function callLamda() {
   $func = $this->lamda;
   return $func();
 }
}
$newfunc = create_function('', 'echo "hoge
\n";');
$h = new Hoge;
$h->set( $newfunc );
$h->callLamda();
?>
It works fine. :-)


tse-webdesign

Here's how to call a runtime-created function from another runtime-created function:
<?php
$get_func = create_function('$func', 'return substr($func,1);');
$get_value = create_function('$index','return pow($index,$index);');
$another_func = create_function('$a', '$func="\x00"."'.$get_func($get_value).'";return $func($a);');
echo $another_func(2); # result is 4
?>


mrben

Here is another tricky but usefull techynote, good for adding "plugin" to a existing class :
<?
class Hoge {
var $lamda;
var $text;
function set($lamda)
{
$this->lamda = $lamda;
}
function callLamda()
{
$func = $this->lamda;
return $func($this);
}
function get()
{
return $this->text;
}
}
$newfunc = create_function('&$class', 'echo $class->get();' );
$h = new Hoge;
$h->text = "Hi there !";
$h->set($newfunc);
$h->callLamda();
?>


joshua e cook

Functions created by create_function() cannot return a value by reference.  The function below creates a function that can.  The arguments are the same as create_function().  Note that these arguments are passed, unmodified, to eval(), so be sure that data passed in is sanitized.
<?php
/**
* create_ref_function
* Create an anonymous (lambda-style) function
* which returns a reference
* see http://php.net/create_function
*/
function
create_ref_function( $args, $code )
{
   static $n = 0;
   $functionName = sprintf('ref_lambda_%d',++$n);
   
   $declaration = sprintf('function &%s(%s) {%s}',$functionName,$args,$body);
   
   eval($declaration);
   
   return $functionName;
}
?>


maxim

for those who want to assign it's own name to a function consider this code:
<?php
$fname = 'hello';
$func = sprintf('
function %s($v="") {
Return "$v
";
}
',
$fname
);
eval($func);
echo $fname('Please print it.... please....');
?>
what it does is,
: Creats a function as a string;
: Replaces the function name with $fname value;
: Converts the string into a REAL php code with eval()
: Calls the function using the variable function as declared before ($fname);
Simple, isn't it?
Can work well as an abstraction layer for portability and/or compatibility purposes
Maxim Maletsky
maxim@maxim.cx // PHPBeginner.com


x-empt a_t ispep.cx

Create_function enables the ability to change the scope of functions.  You might have a class where it needs to define a GLOBAL function.  This is possible, like:
<?php
       class blah {
               function blah() {
                       $z=create_function('$arg1string','return "function-z-".$arg1string;');
                       $GLOBALS['z']=$z;
               }
       }
       $blah_object=new blah;
       $result=$GLOBALS['z']('Argument 1 String');
       echo $result;
?>
Making a function escape it's defined scope can be useful in many situations.


josh

Beware! This is merely a convenience function that generates a unique name for a regular function. It is *not* a closure or even an anonymous function. It is just a regular function that gets named for you.

dan d

Beware when using anonymous functions in PHP as you would in languages like Python, Ruby, Lisp or Javascript.  As was stated previously, the allocated memory is never released; they are not objects in PHP -- they are just dynamically named global functions -- so they don't have scope and are not subject to garbage collection.
So, if you're developing anything remotely reusable (OO or otherwise), I would avoid them like the plague.  They're slow, inefficient and there's no telling if your implementation will end up in a large loop.  Mine ended up in an iteration over ~1 million records and quickly exhasted my 500MB-per-process limit.


neo

Beware of memory-leaks, the garbage-collection seems to 'oversee' dynamically created functions!
I used a function like this to replace special characters in links with their htmlentities:
<?php
$text = preg_replace_callback (
"/(<(frame src|a href|form action)=\")([^\"]+)(\"[^>]*>)/i",
create_function (
'$matches',
'return $matches[1] . htmlentities ($matches[3]) . $matches[4];'
),
$text);
?>
After 1000 calls, the process used about 5MB more than before. In my situation this boosted up the memory-size of one PHP-process up to over 100MB!
In such cases, better store the function in a global variable.


db on music_ml

Apparently you can't refer to a class variable from an anonymous-defined function, inside a class method, using the $this keyword:
<?php
class AnyClass {
 
 var $classVar = 'some regular expression pattern';
 function classMethod() {
   $_anonymFunc = create_function( '$arg', 'if ( eregi($this->classVar, $arg) ) { return true; } else { return false; } ' );
   $wontWork = $_anonymFunc('some string');
 
 }
}
?>
This would throw a warning on 'undefined variable: this'...


ben-php

A nice technique for building complex search patterns on lists, files or whatever is to build function combining functions like this:
<?php
function _not_($f) {
 return create_function('$x',
   "return !$f(\$x);");
}
function _and_($f, $g) {
 return create_function('$x',
   "return $f(\$x) && $g(\$x);");
}
?>
(similarly for _or_ and others...).  Once you've built your matching primitives you can then build more complex matches into your script.
Unfortunately, as explained in (closed) bug #10721, the function names returned by create_function have a null byte at the front and this causes a parse error.
You can fix the definition like this:
<?php
function _not_($f) {
 $f = substr($f, 1);
 return create_function('$x',
   "return !call_user_func(chr(0).'$f', \$x)");
}
?>
The expression that re-builds the function name avoid the null being literally in the parsed string.  If there is a better fix, please let me know.


david

# dynamically create html helper functions which take the args
# $string_contents, $optional_hash_of_options
# and return the contents wrapped in a tag

$html_funcs = Array(
'table',
'tr',
'th',
'td',
'div',
'span',
'pre',
'strong',
'em'
);
$args = '$html, $options=Array()';
$code = '
 $o = "";
 foreach ($options as $a => $b) {
   $o .= " $a=\"$b\"";
 }
 return "<$tag$o>$html</$tag>";
';
foreach ($html_funcs as $key => $tag) {
${$tag} = create_function($args, "\$tag = '$tag'; $code");
}
# usage example:
print $table(
 $tr($th('heading').$td('this is the cell content')),
 Array('style'=>'border: 1px solid silver;')
);


Change Language


Follow Navioo On Twitter
call_user_func_array
call_user_func
create_function
func_get_arg
func_get_args
func_num_args
function_exists
get_defined_functions
register_shutdown_function
register_tick_function
unregister_tick_function
eXTReMe Tracker