create_function

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

create_functionCria uma função dinamicamente avaliando uma string de código

Aviso

Esta função tornou-se DEFASADA a partir do PHP 7.2.0 e foi REMOVIDA a partir do PHP 8.0.0. O uso desta função é fortemente desencorajado.

Descrição

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

Cria uma função dinamicamente a partir dos parâmetros passados e retorna um nome único para ela.

Cuidado

Essa funcão executa um eval() internamente e, por isso, tem os mesmos problemas de segurança de eval(). Além disso, ela tem características ruins de desempenho e uso de memória, porque as funções criadas são globais e não podem ser liberadas da memória.

Uma função anônima nativa deve ser utilizada alternativamente.

Parâmetros

É recomendável passar estes parâmetros como strings em aspas simples. Se forem usadas strings em aspas duplas, os nomes de variáveis no código devem ser escapados com cuidado, ex.: \$somevar.

args

Os argumentos da função, em uma string única, separados por vírgulas.

code

O código da função.

Valor Retornado

Retorna um nome de função único como uma string, ou false em caso de falha. Note que o nome contém um caractere não imprimível ("\0"), portanto deve-se tomar cuidado ao imprimir o nome ou incorporá-lo em qualquer outra string.

Exemplos

Exemplo #1 Criando uma função dinamicamente, com create_function() ou funções anônimas

Pode-se usar uma função criada dinamicamente para (por exemplo) criar uma função a partir de informação obtida em tempo de execução. Primeiro, usando create_function():

<?php
$newfunc
= create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo
$newfunc(2, M_E) . "\n";
?>

Agora o mesmo código, usando uma função anônima; note que o código e os argumentos não estão mais contidos em strings:

<?php
$newfunc
= function($a,$b) { return "ln($a) + ln($b) = " . log($a * $b); };
echo
$newfunc(2, M_E) . "\n";
?>

O exemplo acima produzirá:

ln(2) + ln(2.718281828459) = 1.6931471805599

Exemplo #2 Criação de uma função de processamento geral, com create_function() ou funções anônimas

Outro uso seria ter uma função manipuladora geral que possa aplicar um conjunto de operações a uma lista de parâmetros:

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

// cria uma porção de funções matemáticas
$farr = array(
create_function('$x,$y', 'return "um pouco de trigonometria: ".(sin($x) + $x*cos($y));'),
create_function('$x,$y', 'return "uma hipotenusa: ".sqrt($x*$x + $y*$y);'),
create_function('$a,$b', 'if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;}'),
create_function('$a,$b', "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);"),
create_function('$a,$b', 'if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; }')
);

echo
"\nUsando o primeiro array de funções dinâmicas\n";
echo
"parâmetros: 2.3445, M_PI\n";
process(2.3445, M_PI, $farr);

// agora cria uma porção de funções de processamento de strings
$garr = array(
create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
'e \"$b\"\n** Parecem iguais para mim! (olhando para os 3 primeiros 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
"\nUsando o segundo array de funções dinâmicas\n";
process("Twas brilling and the slithy toves", "Twas the night", $garr);
?>

Novamente, aqui está o mesmo código usando funções anônimas. Note que os nomes das variáveis no código não precisam mais ser escapados, porque não estão em uma string.

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

// cria uma porção de funções matemáticas
$farr = array(
function(
$x,$y) { return "um pouco de trigonometria: ".(sin($x) + $x*cos($y)); },
function(
$x,$y) { return "uma hipotenusa: ".sqrt($x*$x + $y*$y); },
function(
$a,$b) { if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;} },
function(
$a,$b) { return "min(b^2+a, a^2,b) = " . min($a*$a+$b, $b*$b+$a); },
function(
$a,$b) { if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; } }
);

echo
"\nUsando o primeiro array de funções dinâmicas\n";
echo
"parâmetros: 2.3445, M_PI\n";
process(2.3445, M_PI, $farr);

// agora cria uma porção de funções de processamento de strings
$garr = array(
function(
$b,$a) { if (strncmp($a, $b, 3) == 0) return "** \"$a\" " .
"e \"$b\"\n** Parecem iguais para mim! (olhando para os 3 primeiros caracteres)"; },
function(
$a,$b) { return "CRCs: " . crc32($a) . ", ".crc32($b); },
function(
$a,$b) { return "similar(a,b) = " . similar_text($a, $b, $p) . "($p%)"; }
);
echo
"\nUsando o segundo array de funções dinâmicas\n";
process("Twas brilling and the slithy toves", "Twas the night", $garr);
?>

O exemplo acima produzirá:

Usando o primeiro array de funções dinâmicas
parâmetros: 2.3445, M_PI
um pouco de trigonometria: -1.6291725057799
uma hipotenusa: 3.9199852871011
b*a^2 = 4.8103313314525
min(b^2+a, a^2,b) = 8.6382729035898
ln(a)/b = 0.27122299212594

Usando o segundo array de funções dinâmicas
** "Twas the night" e "Twas brilling and the slithy toves"
** Parecem iguais para mim! (olhando para os 3 primeiros caracteres)
CRCs: -725381282, 342550513
similar(a,b) = 11(45.833333333333%)

Exemplo #3 Uso de funções anônimas como funções callback

Talvez o uso mais comum para funções dinâmicas seja passá-las como chamadas de retorno, por exemplo ao usar array_walk() ou usort().

<?php
$av
= array("a ", "uma ", "aquela ", "esta ");
array_walk($av, create_function('&$v,$k', '$v = $v . "manga";'));
print_r($av);
?>

Converted to an anonymous function:

<?php
$av
= array("a ", "uma ", "aquela ", "esta ");
array_walk($av, function(&$v,$k) { $v = $v . "manga"; });
print_r($av);
?>

O exemplo acima produzirá:

Array
(
  [0] => a manga
  [1] => uma manga
  [2] => aquela manga
  [3] => esta manga
)

Ordenando strings do mais longo ao mais curto com create_function():

<?php
$sv
= array("pequena", "uma string grande", "pouco maior", "é uma coisa essa string");
echo
"Original:\n";
print_r($sv);
echo
"Ordenado:\n";
usort($sv, create_function('$a,$b','return strlen($b) - strlen($a);'));
print_r($sv);
?>

Convertida em função anônima:

<?php
$sv
= array("pequena", "uma string grande", "pouco maior", "é uma coisa essa string");
echo
"Original:\n";
print_r($sv);
echo
"Ordenado:\n";
usort($sv, function($a,$b) { return strlen($b) - strlen($a); });
print_r($sv);
?>

O exemplo acima produzirá:

Original:
Array
(
  [0] => pequena
  [1] => uma string grande
  [2] => pouco maior
  [3] => é uma coisa essa string
)
Sorted:
Array
(
  [0] => é uma coisa essa string
  [1] => uma string grande
  [2] => pouco maior
  [3] => pequena
)

Veja Também

add a note add a note

User Contributed Notes 32 notes

up
20
tamagochi_man
5 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
18
Dan D
17 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
2
kak dot serpom dot po dot yaitsam at gmail dot com
11 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
1
kkaiser at revolution-records dot net
16 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
1
info at adaniels dot nl
17 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
2
Josh J
17 years ago
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);
?>
up
0
lombax85 at gmail dot com
2 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
1
Rene Saarsoo
16 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
CertaiN
10 years ago
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];
}
up
0
Dave H
12 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
edgar at goodforall dot eu
14 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):

<?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');
?>
up
0
neo at nowhere dot com
15 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
15 years ago
$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.
up
0
TSE-WebDesign
16 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
17 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
18 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
18 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
*/
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;
}
?>
up
0
boards at gmail dot com
18 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 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
?>
up
0
neo at gothic-chat d0t de
20 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
0
DB on music_ml at yahoo dot com dot ar
20 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
0
x-empt[a_t]ispep.cx
22 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.
up
0
koyama at hoge dot org
23 years ago
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. :-)
up
-2
tomas dot vot at gmail dot com
5 years ago
If you need to upgrade more than one `create_function` to anonymous function, I'm working on a tool that makes dev's life much easier and adaptable for new versions of anything in PHP.

It's tested on 30+ various (and really weird :)) cases, like:

    -$callback = create_function('$a', 'return "<cas:proxy>$a</cas:proxy>";');   
    +$callback = function ($a) {
    +    return "<cas:proxy>{$a}</cas:proxy>";
    +};

Includes concat (.), string quotes and inclined function calls:

    -$func = create_function('$atts, $content = null','return "<div class=\"' . $class_list . '\">" . do_shortcode($content) . "</div>";' );
    +$func = function ($atts, $content = null) use ($class_list) {
    +    return "<div class=\"{$class_list}\">" . do_shortcode($content) . "</div>";
    +};

Do you want to automate the hard work?

1. Instal Rector

    composer require rector/rector --dev

2. Create config

    # rector.yml
    services:
        Rector\Php\Rector\FuncCall\CreateFunctionToAnonymousFunctionRector: ~

3. Upgrade your Code

    vendor/bin/rector process src --config rector.yml --dry-run
    vendor/bin/rector process src --config rector.yml
up
-1
CertaiN
10 years ago
How to save memory-space:

<?php

function create_lambda($args, $code) {
    static
$list = array();
   
$i = "{$args}\0{$code}";
    if (!isset(
$list[$i])) {
       
$list[$i] = create_function($args, $code);
    }
    return
$list[$i];
}
up
-1
Its Will
13 years ago
If you create a function that will only be used from an object context (i.e. you want a dynamic method that can then call methods from the original object, still maintaining access to the object's runtime values) then you can use the following functions I have created (ob_lambda_func and ob_lambda) to enable the dynamic function to easily call *public* methods on the object, in their runtime contexts:

<?php
/* the OB Lambda functions allow a lambda function to call a method from its callee's object */
if(!function_exists('ob_lambda_func')){
function
ob_lambda_func($method, $args) {
   if((
phpversion()+0)<5.1 || (substr(phpversion(),2)+0)<1.1)
       die(
"\nError: This script requires PHP v5.1.1+!\n");
  
$bt=debug_backtrace();
   foreach(
$bt as $xsp) {
       if(isset(
$xsp['object'])) {
           if(!
method_exists($xsp['object'], $method)) continue;
           return
call_user_func_array(array($xsp['object'], $method), $args);
       }
   }
   if(!
function_exists($method))
       die(
"\nOB: Internal Error! ($method)");
   return
call_user_func_array($method, $args);
}}
if(!
function_exists('ob_lambda')){
function
ob_lambda($method) {
   return
create_function('','$args=func_get_args(); return ob_lambda_func('.var_export($method, true).',$args);');
}}

/* Usage:
*   For each callable method, store the results of ob_lambda('method_name')
*   When a lambda function you call wants to access one of these methods,
*    you need to pass it the result of ob_lambda for that method, the easiest
*    way is to have one of the lambda functions arguments accept the result
*       i.e.:  $myFunc=ob_lambda('myMethod');
*              $lf1=create_function('$func', '$func( ... args ... )');
*              $lf1($myFunc);
*    because create_function prepends a \0 to the function name, it is difficult
*    to pass the result of ob_lambda to the target function without using an argument
*/
/* here is an example -- lambda function Foo::test can call Foo::Bar and Foo::Baz, and these  */
class Foo {
    private
$bar, $baz, $test;
    private
$runtimeValue=0;
    function
__construct() {
       
$this->runtimeValue=rand();
       
$this->bar=ob_lambda('Bar');
       
$this->baz=ob_lambda('Baz');
       
$this->test=create_function(
           
'$bar, $baz',
           
'$bar("Hello, World!"); $baz();'
       
);
    }
    function
Test() {
       
$fn=$this->test;
       
$fn($this->bar, $this->baz);
    }
    function
Bar($a) {
        echo
"$a: Bar ($this->runtimeValue)\n";
    }
    function
Baz() {
        echo
"and another! Baz ($this->runtimeValue)\n";
    }
}

$foo=new Foo();
// Foo::Bar("Testing Other Method"); <-- this causes fatal error
//  (using $this when not in object context)
$foo->Test();

?>

This snippet (with test) shows how the lambda function $foo->test can call Foo::Bar and Foo::Baz without an explicit reference to the original object. The methods are run from their object context, and so can access the runtime-modified variable $foo->runtimeValue, which is set to a random number on construction.
The function definition for $foo->test is the following:
function ($bar, $baz) {
    $bar("Hello, World!");
    $baz;
}
As you can see, it is clean and simple, with no obvious artifacts from the use of OB Lambda

The expected output should be:
Hello, World!: Bar (440048505)
and another! Baz (440048505)

Or any other random number in place of 440048505
Make sure, before you change your code, that your target server has PHP 5.1.1+, or these functions won't work and will return an error!
Hope this helps anyone as much as it has me! :)
up
-1
v dot churakov at i2d dot ru
14 years ago
<?

function is_function( &$mixed )
{
    if ( is_object( $mixed ) ) {
        return ( $mixed instanceof Closure );
    } elseif( is_string( $mixed ) ) {
        return function_exists( $mixed );
    } else {
        return false;
    }
}

function myfunc(){}

$test = 123;
echo  is_function( $test ); //will return false

$test = 'isset';
echo  is_function( $test ); //will return false... it's not work with reserved :( ...

$test = 'myfunc';
echo  is_function( $test ); //will return true

$test = create_function( '', 'echo 123;' );
echo  is_function( $test ); //will return true

$test = function () { echo 123; };
echo  is_function( $test ); //will return true

?>
up
-1
ionix at NOSPAM dot post dot com
10 years ago
I experimented a bit in creating a lambda function using a variable amount of arguments. While I couldn't find an efficient way to create a random bit of code, I was able to get it to behave as a front end for existing functions (as well as user-defined of course).

The code required me to use the dreaded eval() function to get it to use a variable amount of parameters, so be sure that all input is thoroughly cleaned if derived from the user.

<?php

   
function run_function( $function )
    {
       
// Get Arguments, Unset Exisitng Parameter
       
$params = func_get_args();
        unset(
$params[0] );

        if( (
$count = count( $params ) ) > 0 )
        {
           
$args = '$a';
           
$inc = 'b';

           
// Create Argument String - Formats as '$a, $b, $c' Per Number of Arguments
           
for( $x = 1; $x < $count; $x++ )
            {
               
$args .= ', $' . $inc;
               
$inc++;
            }

           
// Create Lambda Function and Format Paramters
           
$lambda = create_function( $args, 'return ' . $function . '(' . $args . ');' );
           
$params = "'" . implode('\', \'', $params) . "'";

           
// Build and Evaluate Function with Parameters
           
$eval = '$return = $lambda(' . $params . ');';
            eval(
$eval);

            return
$return;
        }
        else
        {
            return
false;
        }
    }
?>

For most applications you would be better off calling the function normally. Perhaps this little proof of concept may find some use if adapted to work by someone who requires it.
up
-3
131 dot php at cloudyks dot org
11 years ago
For those who want to create closure with create_function, don't bother, you can't.
Use create_closure instead :p

<?php
//same thing as create_function, but returns a closure..( 5.4)
function create_closure($args, $body){
  return eval(
"return function($args){ {$body}  };");
}
?>
up
-1
MagicalTux at FF.ST
20 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
-2
coleyeder at gmail dot com
10 years ago
Default values works:

<?php

$f
= create_function('$a,$b=3', 'var_dump($a, $b);');
$f(1);

// output:

// int(1)
// int(3)

?>
up
-1
maxim at maxim dot cx
22 years ago
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
up
-2
mrben at free dot fr
23 years ago
Here is another tricky but usefull techynote, good for adding "plugin" to a existing class :

<?php

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();

?>
To Top