create_function

(PHP 4 >= 4.0.1, PHP 5, PHP 7)

create_functionCrear una función anónima (estilo lambda)

Descripción

create_function(string $args, string $code): string

Crea una función anónima desde los parámetros pasados, y devuelve un nombre único para ella.

Precaución

Esta función realiza internamente un eval() y como tal tiene los mismos problemas de seguridad que eval(). Además posee características malas de rendimiento y uso de memoria.

Si se usa 5.3.0 o superior, se debería usar en su lugar una función anónima nativa.

Parámetros

Normalmente estos parámetros serán pasados como una cadena entre comillas simples. La razón de usar comillas simples es proteger a los nombres de las variables de ser analizados, de otro modo, si se usan comillas dobles habrá necesidad de escapar los nombres de las variables, p.ej. \$avar.

args

Los argumentos de la función.

code

El código de la función.

Valores devueltos

Devuelve un nombre de función único como cadena, o false en caso de error.

Ejemplos

Ejemplo #1 Crear una función anónima con create_function()

Se puede usar esta función para, por ejemplo, crear una función desde información reunida en tiempo de ejecución:

<?php
$nuevafunc
= create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo
"Nueva función anónima: $nuevafunc\n";
echo
$nuevafunc(2, M_E) . "\n";
// imprime
// Nueva función anónima: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
?>

O quizás para tener una función gestora general que pueda aplicar un conjunto de operaciones a una lista de parámetros:

Ejemplo #2 Hacer una función de proceso general con create_function()

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

// crear un puñado de funciones matemáticas
$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 "algo de trigonometría: ".(sin($x) + $x*cos($y));'),
create_function('$x,$y', 'return "una hipotenusa: ".sqrt($x*$x + $y*$y);'),
create_function('$a,$b', $f1),
create_function('$a,$b', $f2),
create_function('$a,$b', $f3)
);

echo
"\nUsar la primera matriz de funciones anónimas\n";
echo
"parámetros: 2.3445, M_PI\n";
procesar(2.3445, M_PI, $farr);

// ahora hacer un puñado de funciones de proceso de cadenas
$garr = array(
create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
'y \"$b\"\n** ¡Para mí se parecen! (mirando los 3 primeros caracteres)";'),
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
"\nUsar la segunda matriz de funciones anónimas\n";
procesar("Cuando los pájaros cantan", "Cuando es de noche", $garr);
?>

El resultado del ejemplo sería:

Usar la primera matriz de funciones anónimas
parámetros: 2.3445, M_PI
algo de trigonometría: -1.6291725057799
una hipotenusa: 3.9199852871011
b*a^2 = 4.8103313314525
min(b^2+a, a^2,b) = 8.6382729035898
ln(a)/b = 0.27122299212594

Usar la segunda matriz de funciones anónimas
** "Cuando es de noche" y "Cuando los pájaros cantan"
** ¡Para mí se parecen! (mirando los 3 primeros caracteres)
CRCs: -725381282, 342550513
similar(a,b) = 11(45.833333333333%)

Pero quizás el uso más común de las funciones estilo lambda (anónimas) sea el de crear funciones de llamada de retorno, por ejemplo cuando se usa array_walk() o usort()

Ejemplo #3 Usar funciones anónimas como funciones de llamada de retorno

<?php
$av
= array("el ", "un ", "ese ", "este ");
array_walk($av, create_function('&$v,$k', '$v = $v . "mango";'));
print_r($av);
?>

El resultado del ejemplo sería:

Array
(
  [0] => el mango
  [1] => un mango
  [2] => ese mango
  [3] => este mango
)

una matriz de cadenas ordenada de más corta a más larga

<?php

$sv
= array("pequeña", "más larga", "una gran cadena", "esto es una 'señora' cadena");
print_r($sv);

?>

El resultado del ejemplo sería:

Array
(
  [0] => pequeña
  [1] => más larga
  [2] => una gran cadena
  [3] => esto es una 'señora' cadena
)

ordenarla de más larga a más corta

<?php

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

?>

El resultado del ejemplo sería:

Array
(
  [0] => esto es una 'señora' cadena
  [1] => una gran cadena
  [2] => más larga
  [3] => pequeña
)

Ver también

add a note

User Contributed Notes 22 notes

up
21
tamagochi_man
6 years ago
Whilst it was correct 11 years ago, the statement of Dan D is not so correct any moreю Anonymous functions are now objects of a class Closure and are safely collected by garbage collector.
up
13
Dan D
18 years ago
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.
up
3
Josh J
18 years ago
In regards to the recursion issue by info at adaniels dot nlAnon 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);?>
up
3
kak dot serpom dot po dot yaitsam at gmail dot com
13 years ago
Try this to boost performance of your scripts (increase maxCacheSize):

<?php
runkit_function_copy('create_function', 'create_function_native');
runkit_function_redefine('create_function', '$arg,$body', 'return __create_function($arg,$body);');

function __create_function($arg, $body) {
    static $cache = array();
    static $maxCacheSize = 64;
    static $sorter;

    if ($sorter === NULL) {
        $sorter = function($a, $b) {
            if ($a->hits == $b->hits) {
                return 0;
            }

            return ($a->hits < $b->hits) ? 1 : -1;
        };
    }

    $crc = crc32($arg . "\\x00" . $body);

    if (isset($cache[$crc])) {
        ++$cache[$crc][1];
        return $cache[$crc][0];
    }

    if (sizeof($cache) >= $maxCacheSize) {
        uasort($cache, $sorter);
        array_pop($cache);
    }

    $cache[$crc] = array($cb = eval('return function('.$arg.'){'.$body.'};'), 0);
    return $cb;
}
?>
up
2
kkaiser at revolution-records dot net
18 years ago
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:

<?php
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:

<?php
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:

<?php
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.
up
2
info at adaniels dot nl
19 years ago
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?>
up
1
Dave H
14 years ago
The following function is very useful for creating an alias of a user function. 
For built-in functions, it is less useful because default values are not available, so function aliases for built-in functions must have all parameters supplied, whether optional or not.

<?php
function create_function_alias($function_name, $alias_name)
{
    if(function_exists($alias_name))
        return false;
    $rf = new ReflectionFunction($function_name);
    $fproto = $alias_name.'(';
    $fcall = $function_name.'(';
    $need_comma = false;
    
    foreach($rf->getParameters() as $param)
    {
        if($need_comma)
        {
            $fproto .= ',';
            $fcall .= ',';
        }

        $fproto .= '$'.$param->getName();
        $fcall .= '$'.$param->getName();

        if($param->isOptional() && $param->isDefaultValueAvailable())
        {
            $val = $param->getDefaultValue();
            if(is_string($val))
                $val = "'$val'";
            $fproto .= ' = '.$val;
        }
        $need_comma = true;
    }
    $fproto .= ')';
    $fcall .= ')';

    $f = "function $fproto".PHP_EOL;
    $f .= '{return '.$fcall.';}';

    eval($f);
    return true;
}
?>
up
0
lombax85 at gmail dot com
4 years ago
For who *really* needs the create_function() on php8 (because of legacy code that cannot be changed easily) there is this: "composer require lombax85/create_function".
up
0
neo at nowhere dot com
16 years ago
In response to kkaiser at revolution-records dot net's note, even tho PHP will allow you to use <?$myfunc = create_function('$this', $code);?>You can NOT use a reference to "$this" inside of the anonymous function, as PHP will complain that you are using a reference to "$this" in a non-object context.Currently, I have not found a work-around for this...
up
0
Alan FUNG
17 years ago
$f = create_function('','echo "function defined by create_function";');$f();result:function defined by create_functionYou may define no return in function body while you are using create_function.
up
0
Rene Saarsoo
17 years ago
Here has been some discussion about the "memory leak" create_function() can create.What create_function() actually does, is creating an ordinary function with name chr(0).lambda_n where n is some number:<?php$f = create_function('', 'return 1;');function lambda_1() { return 2; }$g = "lambda_1";echo $g(); // outputs: 2$h = chr(0)."lambda_1";echo $h(); // outputs: 1?>
up
0
TSE-WebDesign
18 years ago
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?>
up
0
Phlyst
18 years ago
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);        }    }');?>
up
0
josh at janrain dot com
19 years ago
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.
up
0
Joshua E Cook
19 years ago
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 */functioncreate_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;}?>
up
0
boards at gmail dot com
19 years ago
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 wantif (empty($fnc)) {  die('Could not create function $fnc.');}# although, the follow will NOT workif (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?>
up
0
MagicalTux at FF.ST
21 years ago
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).
up
0
DB on music_ml at yahoo dot com dot ar
22 years ago
[EDIT by danbrown AT php DOT net: Combined user-corrected post with previous (incorrect) post.]

You can't refer to a class variable from an anonymous function inside a class method using $this.  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);
 
 }

}
?>
up
-1
CertaiN
11 years ago
Best wapper:<?phpfunction create_lambda($args, $code) {    static $func;    if (!isset($func[$args][$code])) {        $func[$args][$code] = create_function($args, $code);    }    return $func[$args][$code];}
up
-1
edgar at goodforall dot eu
16 years ago
Just a little toy I thought up, I would like to share. Creates an anonymous function, which let you use a class  as a function.In php 5.3 there is support for real functors  (trough __invoke):<?phpfunction createFunctor($className){        $content = "                static \$class;                if(!\$class){                        \$class = new $className;                }                return \$class->run(\$args);        ";        $f = create_function('$args', $content);        return $f;}class test {        public function run($args){                print $args;        }}$test = createFunctor('test');$test('hello world');?>
up
-1
neo at gothic-chat d0t de
21 years ago
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.
up
-1
x-empt[a_t]ispep.cx
24 years ago
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.
To Top