80

e.g.:

$functions = array(
  'function1' => function($echo) { echo $echo; }
);

Is this possible? What's the best alternative?

Kirk Ouimet
  • 27,280
  • 43
  • 127
  • 177
  • 3
    **TL;DR - since PHP 5.4:** `$functions = [ 'function1' => function($echo){ echo $echo; } ];` ......since PHP 5.3 anonymous functions are available, since 5.4 you can write `[]` instead of `array()` – jave.web May 10 '16 at 13:40

7 Answers7

164

The recommended way to do this is with an anonymous function:

$functions = [
  'function1' => function ($echo) {
        echo $echo;
   }
];

If you want to store a function that has already been declared then you can simply refer to it by name as a string:

function do_echo($echo) {
    echo $echo;
}

$functions = [
  'function1' => 'do_echo'
];

In ancient versions of PHP (<5.3) anonymous functions are not supported and you may need to resort to using create_function (deprecated since PHP 7.2):

$functions = array(
  'function1' => create_function('$echo', 'echo $echo;')
);

All of these methods are listed in the documentation under the callable pseudo-type.

Whichever you choose, the function can either be called directly (PHP ≥5.4) or with call_user_func/call_user_func_array:

$functions['function1']('Hello world!');

call_user_func($functions['function1'], 'Hello world!');
Alex Barrett
  • 16,175
  • 3
  • 52
  • 51
  • about call_user_func: Is $var = $functions["function1"], when function1 returns a value, bad practice? – Roy Feb 10 '14 at 22:38
  • 2
    Hi @Roy. As `$functions["functions1"]` contains a callable assigning it to `$var` will cause `$var` to also contain a callable. You would still need to call it with `$var()` to get the return value. – Alex Barrett Feb 11 '14 at 17:19
  • 2
    Just found a slight bug that the PHP 5.3 method doesn't work if the array is a class member such as: class MyClass { $functions = [ 'function1' => function($echo) { echo $echo; } ]; } – Zack Morris Feb 24 '16 at 21:50
  • @ZackMorris comment should be pointed out in the answer since it isn't an unreasonable idea to do this in a class (it happened at least twice to me before finding his comment) – frollo Sep 20 '16 at 12:29
  • @frollo I think you and Zack are encountering a slightly different issue. You can store functions in class members just fine but you can't do so _at compile time_. See this answer for more info: http://stackoverflow.com/a/28832820/69713 – Alex Barrett Sep 21 '16 at 00:08
  • Well, I tried Zack's code and it didn't work for me so I thought it was the same problem. If it has been fixed I will ask my IT about updating the server, maybe we missed something – frollo Sep 21 '16 at 07:24
  • Looks like quotes around do_echo is not necessary in this example function do_echo($echo) { echo $echo; } $functions = array( 'function1' => 'do_echo' ); I have used like: do_echo() – Kirill A Mar 28 '18 at 13:23
  • 5
    from [php.net](http://php.net/manual/en/function.create-function.php) **`Warning This function has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.`** – ghabriel Sep 19 '18 at 05:18
  • Would you mind updating the answer with PHP 7.4 version (arrow functions) and adding a warning about deprecated `create_function()`? – Dharman Mar 01 '20 at 14:21
11

Since PHP "5.3.0 Anonymous functions become available", example of usage:

note that this is much faster than using old create_function...

//store anonymous function in an array variable e.g. $a["my_func"]
$a = array(
    "my_func" => function($param = "no parameter"){ 
        echo "In my function. Parameter: ".$param;
    }
);

//check if there is some function or method
if( is_callable( $a["my_func"] ) ) $a["my_func"](); 
    else echo "is not callable";
// OUTPUTS: "In my function. Parameter: no parameter"

echo "\n<br>"; //new line

if( is_callable( $a["my_func"] ) ) $a["my_func"]("Hi friend!"); 
    else echo "is not callable";
// OUTPUTS: "In my function. Parameter: Hi friend!"

echo "\n<br>"; //new line

if( is_callable( $a["somethingElse"] ) ) $a["somethingElse"]("Something else!"); 
    else echo "is not callable";
// OUTPUTS: "is not callable",(there is no function/method stored in $a["somethingElse"])

REFERENCES:

jave.web
  • 13,880
  • 12
  • 91
  • 125
9

Warning create_function() has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.

To follow up on Alex Barrett's post, create_function() returns a value that you can actually use to call the function, thusly:

$function = create_function('$echo', 'echo $echo;' );
$function('hello world');
Dharman
  • 30,962
  • 25
  • 85
  • 135
RibaldEddie
  • 5,136
  • 2
  • 23
  • 22
2

Not mentioned yet: arrow functions (7.4+) are useful for keeping syntax terse and capturing read-only properties from the enclosing scope.

<?php

$ops = [
    'add' => fn($x, $y) => $x + $y,
    'sub' => fn($x, $y) => $x - $y,
    'mul' => fn($x, $y) => $x * $y,
    'div' => fn($x, $y) => $x / $y,
];

// test it
var_dump($ops['add'](6, 2)); // => 8
var_dump($ops['sub'](6, 2)); // => 4
var_dump($ops['mul'](6, 2)); // => 12
var_dump($ops['div'](6, 2)); // => 3

foreach ($ops as $name => $fn) {
    echo "$name => " . $fn(6, 2) . "\n";
}
ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • I would say this example is not very informative, as for some reason it hides the actual arrow function behind regular functions. Only a person already familiar with arrow functions will recognize it. Why not to rewrite the entire example to arrow functions, making it much cleaner easier to grasp? – Your Common Sense May 16 '23 at 06:10
  • @YourCommonSense Thanks for the feedback. I tried updating, hopefully it's clearer even though I'm not showing binding any longer. – ggorlen May 16 '23 at 14:20
1

Because I could...

Expanding on Alex Barrett's post.

I will be working on further refining this idea, maybe even to something like an external static class, possibly using the '...' token to allow variable length arguments.

In the following example I have used the keyword 'array' for clarity however square brackets would also be fine. The layout shown which employs an init function is intended to demonstrate organization for more complex code.

<?php
// works as per php 7.0.33

class pet {
    private $constructors;

    function __construct() {
        $args = func_get_args();
        $index = func_num_args()-1;
        $this->init();

        // Alex Barrett's suggested solution
        // call_user_func($this->constructors[$index], $args);  

        // RibaldEddie's way works also
        $this->constructors[$index]($args); 
    }

    function init() {
        $this->constructors = array(
            function($args) { $this->__construct1($args[0]); },
            function($args) { $this->__construct2($args[0], $args[1]); }
        );
    }

    function __construct1($animal) {
        echo 'Here is your new ' . $animal . '<br />';
    }

    function __construct2($firstName, $lastName) {
        echo 'Name-<br />';
        echo 'First: ' . $firstName . '<br />';
        echo 'Last: ' . $lastName;
    }
}

$t = new pet('Cat');
echo '<br />';
$d = new pet('Oscar', 'Wilding');
?>

Ok, refined down to one line now as...

function __construct() {
    $this->{'__construct' . (func_num_args()-1)}(...func_get_args());
}

Can be used to overload any function, not just constructors.

Stuperfied
  • 322
  • 2
  • 10
0

By using closure we can store a function in a array. Basically a closure is a function that can be created without a specified name - an anonymous function.

$a = 'function';
$array=array(
    "a"=> call_user_func(function() use ($a) {
        return $a;
    })
);
var_dump($array);
dhamo dharan
  • 712
  • 1
  • 10
  • 25
-1

Here is what worked for me

function debugPrint($value = 'll'){

    echo $value; 
}

$login = '';


$whoisit = array( "wifi" => 'a', "login" => 'debugPrint', "admin" => 'c' );
 
foreach ($whoisit as $key => $value) {
     
    if(isset($$key)) {  
     // in this case login exists as a variable and I am using the value of login to store the function I want to call 
        $value(); } 
}
cigien
  • 57,834
  • 11
  • 73
  • 112