create_function

(PHP 4 >= 4.0.1, PHP 5)

create_function — Создаёт анонимную (lambda-style) функцию

Описание

string create_function ( string $args , string $code )

Создаёт анонимную функцию из переданных параметров и возвращает её уникальное имя. Обычно args передаются строкой в апострофах, что также рекомендуется для параметра code . Основанием для использования строк в апострофах является защита имён переменных от обработки, другими словами, если вы будете использовать кавычки, вам будет нужно экранировать все имена переменных вот так: \$avar.

Вы можете использовать эту функцию (к примеру) для создания функций на основании информации, полученной во время выполнения программы:

Пример #1 Создание анонимной функции с помощью create_function()

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

Или, возможно, чтобы иметь общий обработчик для применения набора функций к списку параметров:

Пример #2 Создание функции-обработчика с помощью create_function()

<?php
function process($var1$var2$farr
{
    for (
$f=0$f count($farr); $f++) {
        echo 
$farr[$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.3445M_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);
?>

Вышеприведённый код выводит следующее:

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%)

Однако, вероятно, наиболее обоснованное использование lambda-style (анонимных) функций - это создание функций-обработчиков, например, при использовании array_walk() или usort()

Пример #3 Использование анонимной функции как функции-обработчика

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

выводит:

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

Сортировка строк по их длине

<?php

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

?>

результат:

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

Теперь отсортируем их в обратном порядке:

<?php

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

?>

результат:

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

Коментарии

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.
2001-07-05 14:41:22
http://php5.kiev.ua/manual/ru/function.create-function.html
[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);
 
 }

}
?>
2003-04-02 07:58:07
http://php5.kiev.ua/manual/ru/function.create-function.html
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.
2004-01-20 22:54:19
http://php5.kiev.ua/manual/ru/function.create-function.html
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).
2004-03-09 12:25:09
http://php5.kiev.ua/manual/ru/function.create-function.html
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
?>
2005-12-31 13:18:17
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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;
}
?>
2006-01-19 18:43:57
http://php5.kiev.ua/manual/ru/function.create-function.html
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.
2006-03-03 12:21:53
http://php5.kiev.ua/manual/ru/function.create-function.html
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
?>
2006-05-10 18:42:34
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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);
?>
2006-09-27 15:45:52
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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);
        }
    }'
);
?>
2006-10-06 08:10:23
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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.
2006-10-23 22:22:04
http://php5.kiev.ua/manual/ru/function.create-function.html
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.
2007-04-13 16:10:09
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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
?>
2007-08-18 12:55:57
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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
?>
2008-02-06 04:31:10
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
$f = create_function('','echo "function defined by create_function";');
$f();

result:
function defined by create_function

You may define no return in function body while you are using create_function.
2008-08-07 03:24:36
http://php5.kiev.ua/manual/ru/function.create-function.html
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...
2008-08-28 04:56:57
http://php5.kiev.ua/manual/ru/function.create-function.html
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):

<?php
function 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');
?>
2009-07-02 10:45:30
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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;
}
?>
2011-03-24 08:47:01
http://php5.kiev.ua/manual/ru/function.create-function.html
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;
        };
    }

   
$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;
}
?>
2012-06-27 03:17:08
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
Best wapper:

<?php

function create_lambda($args$code) {
    static 
$func;
    if (!isset(
$func[$args][$code])) {
       
$func[$args][$code] = create_function($args$code);
    }
    return 
$func[$args][$code];
}
2013-09-20 02:49:25
http://php5.kiev.ua/manual/ru/function.create-function.html
Автор:
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.
2018-10-09 10:44:07
http://php5.kiev.ua/manual/ru/function.create-function.html
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".
2021-04-18 17:40:30
http://php5.kiev.ua/manual/ru/function.create-function.html

    Поддержать сайт на родительском проекте КГБ