|
|
 |
create_function (PHP 4 >= 4.0.1, PHP 5) create_function -- Create an anonymous (lambda-style) function Descriptionstring create_function ( string args, string code )
Creates an anonymous function from the parameters passed, and
returns a unique name for it. Usually the
args will be passed as a single quote
delimited string, and this is also recommended for the
code. 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.
You can use this function, to (for example) create a function
from information gathered at run time:
Example 1.
Creating an anonymous function with create_function()
|
<?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";
?>
|
|
Or, perhaps to have general handler function that can apply a set
of operations to a list of parameters:
Example 2.
Making a general processing function with
create_function()
|
<?php
function process($var1, $var2, $farr)
{
for ($f=0; $f < count($farr); $f++) {
echo $farr[$f]($var1, $var2) . "\n";
}
}
$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);
$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);
?>
|
and when you run the code above, the output will be:
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()
Example 3. 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);
?>
|
outputs:
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);
?>
|
outputs:
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);
?>
|
outputs:
Array
(
[0] => it is a string thing
[1] => a big string
[2] => larger
[3] => small
) |
|
User Contributed Notes
create_function
jsb17 at NOSPAMcornell dot edu
19-Apr-2005 02:38
To clarify this comment below, "Basically, if create_function() is the answer, you arn't asking the right question":
Using eval() and create_function() is like pushing the queen early. Chessmasters can do it because they know what they're doing. Beginners and intermediates, however, are quick to attack without recognizing the long term danger.
So too, programmers who have *actually completed a curriculum in computer science* and are aware of their algorithmic options and computational complexities, can find incredible possibilities for eval() and create_function() and should find no fear in calling those functions.
However, if you're a novice or intermediate, it may be wise to put aside your pride and seek advice from a computer scientist on a simpler algorithm to your solve problem. You wouldn't want a nurse to perform the work of a surgeon on you.
evildictaitor at hotmail dot com
13-Apr-2005 01:51
As a general rule, along with eval(), you should avoid using this function AT ALL COSTS, as it requires PHP to load it's entire engine into runtime, instead of simply compiling to pseudo-binary and executing.
In laymans terms, the overhead of using eval() or create_function() in one medium to large program is about three times that of not using it.
The only reason I can see of using this function is for use with rename_function() or override_function() for preventing access to a function (if auto-prepend is used) or for debug purposes.
Why use create_function, when you can specify it as arguments anyways?
Basically, if create_function() is the answer, you arn't asking the right question.
david [at] davelee.com.au
13-Apr-2005 04:15
# 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;')
);
endofyourself at yahoo dot com
07-Oct-2004 02:17
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.
MagicalTux at FF.ST
09-Mar-2004 12:25
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).
neo at gothic-chat d0t de
20-Jan-2004 10:54
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.
nospam at fiderallalla dot de
08-Aug-2003 08:39
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
DB on music_ml at yahoo dot com dot ar
02-Apr-2003 06:58
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);
}
}
?>
DB on music_ml at yahoo dot com dot ar
02-Apr-2003 04:04
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'...
listes at brissambre dot org
14-Aug-2002 12:22
[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.
ben-php at bacarisse dot btinternet dot co dot uk
26-Jul-2001 03:33
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.
x-empt[a_t]ispep.cx
05-Jul-2001 01:41
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.
maxim at maxim dot cx
27-Apr-2001 05:26
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<BR>";
}
',
$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
mrben at free dot fr
20-Feb-2001 10:33
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();
?>
koyama at hoge dot org
14-Dec-2000 06:22
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<br>\n";');
$h = new Hoge;
$h->set( $newfunc );
$h->callLamda();
?>
It works fine. :-)
| |