Як мені негайно виконати анонімну функцію в PHP?


96

У JavaScript ви можете визначити анонімні функції, які виконуються негайно:

(function () { /* do something */ })()

Чи можете ви зробити щось подібне в PHP?


2
У мене немає PHP 5.3 на руках, щоб спробувати, але як це call_user_func(function(){/* stuff */})зробити?
Джаспер

Відповіді:


121

Щодо PHP7: див. Відповідь Ясуо Огакі :(function() {echo 'Hi';})();

Для попередніх версій: єдиний спосіб їх негайного виконання - я можу придумати

call_user_func(function() { echo 'executed'; });

12
Якщо не буде введено функціонування ланцюжка викликів , це також буде моя пропозиція.
салата

2
@Gordon: php 5.4 все ще нічого?
динамічний

@ yes123 ні. все ще доведеться використовуватиcall_user_func
Гордон

2
@BennettMcElwee, скажімо так: навіть якщо це працює дещо повільніше, ніж альтернатива define-assign-call, ймовірність того, що це створить значне вузьке місце у вашому додатку, дуже низька. у разі сумнівів профілюйте свій додаток у реальних умовах.
Гордон,

Дякую @Gordon, ось що я думав. У мене склалося враження, що salathe та yes123 не задоволені цим методом, і я здивувався чому. Мені здається цілком добре.
Bennett McElwee,

28

In PHP 7- зробити те саме в javascript

$gen = (function() {
    yield 1;
    yield 2;

    return 3;
})();

foreach ($gen as $val) {
    echo $val, PHP_EOL;
}

echo $gen->getReturn(), PHP_EOL;

Вихід:

1
2
3

15

Ну звичайно, ви можете використовувати call_user_func, але є ще одна досить проста альтернатива:

<?php
// we simply need to write a simple function called run:
function run($f){
    $f();
}

// and then we can use it like this:
run(function(){
    echo "do something";
});

?>

1
Я хочу негайно виконати функцію, тому що функція, яку я визначаю, та, яку НЕ ПОВИННО викликати більше одного разу при звичайному виконанні. Проблема з визначенням іменованої функції run (), як і у вас, полягає в тому, що будь-хто інший, хто бачить код, може подумати, що він може також викликати run () в якійсь іншій частині коду. Функція негайного запуску дає зрозуміти, що цей код не можна запускати двічі.
Даніель Говард

3
Вони не можуть викликати runвашу функцію в якійсь іншій частині коду, оскільки після рядка, який негайно її виконує, не існує дескриптора вашої функції.
Pacerier

3
@DanielHoward Сенс run()полягає у негайному виконанні неназваної функції, переданої йому. Так само call_user_func(), як тільки параметри не передаються.
Сайфер

1
@JordanLev, Він має простішу реалізацію (лише один рядок:) $f();і може бути швидшим, якщо движок, який ти використовуєш, не оптимізує для особливого випадку, де call_user_funcє лише один аргумент функції. Це тому, що call_user_funcпідтримує передачу декількох параметрів, і це перший аргумент підтримує або рядок як аргумент, або функцію. Тим не менш, якщо call_user_funcце читається набагато, я б не використовував, runякщо код не знаходиться десь внизу піраміди .
Pacerier

1
@JordanLev, "простіша реалізація" відноситься до порівняння між кодом всередині функцій runта call_user_func. call_user_funcмає невід'ємний недолік у порівнянні з runтим, що runробить лише одне, тоді як call_user_funcпідтримує додаткові функції на додаток до того, що runробить. Ви можете спробувати швидкий тест циклу ( наприклад ), щоб побачити, що швидше на вашому двигуні.
Pacerier

11

Це найпростіший варіант для PHP 7.0 або новішої версії.

php -r '(function() {echo 'Hi';})();'

Це означає створити закриття, а потім викликати його як функцію, дотримуючись "()". Працює так само, як JS, завдяки єдиному порядку оцінки змінних.

https://3v4l.org/06EL3


2
Гарна відповідь, але чому ви форматуєте це як операцію командного рядка?
Кодос Джонсон

6
(new ReflectionFunction(function() {
 // body function
}))->invoke();

6
Ви можете надати більше деталей? може додати пояснення?
MoralCode

2

Примітка, прийнята відповідь - це добре, але це займає 1,41x довше (на 41% повільніше), ніж оголошення функції та виклик її у два рядки.

[Я знаю, що це насправді не нова відповідь, але я відчув, що було цінним додати це десь для відвідувачів.]

Деталі:

<?php
# Tags: benchmark, call_user_func, anonymous function 
require_once("Benchmark.php");
bench(array(
        'test1_anonfunc_call' => function(){
                $f = function(){
                        $x = 123;
                };
                $f();
        },
        'test2_anonfunc_call_user_func' => function(){
                call_user_func(
                        function(){
                                $x = 123;
                        }
                );
        }
), 10000);
?>

Результати:

$ php test8.php
test1_anonfunc_call took 0.0081379413604736s (1228812.0001172/s)
test2_anonfunc_call_user_func took 0.011472940444946s (871616.13432805/s)

0

Я спробував це таким чином, але це більш багатослівно, ніж відповідь у верхній частині, використовуючи будь-який оператор (або функцію), який дозволяє визначити функцію спочатку:

    $value = $hack == ($hack = function(){
            // just a hack way of executing an anonymous function
            return array(0, 1, 2, 3);                
    }) ? $hack() : $hack();

2
Тоді чому не просто $hack = function(){...}; $hack()?

0

Це не пряма відповідь, а обхідний шлях. Використання PHP> = 7. Визначення анонімного класу за допомогою названого методу та побудова класу та негайний виклик методу.

$var = (new class() { // Anonymous class
    function cool() { // Named method
        return 'neato';
    }
})->cool(); // Instantiate the anonymous class and call the named method
echo $var; // Echos neato to console.

-2

Не виконується відразу, але близько до;)

<?php

$var = (function(){ echo 'do something'; });
$var();

?>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.