ฉันจะเรียกใช้ฟังก์ชันนิรนามใน PHP ทันทีได้อย่างไร


96

ใน JavaScript คุณสามารถกำหนดฟังก์ชันที่ไม่ระบุชื่อที่เรียกใช้งานได้ทันที:

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

คุณสามารถทำสิ่งนั้นใน PHP ได้หรือไม่?


2
ฉันไม่มี php 5.3 ในมือให้ลองใช้ แต่จะcall_user_func(function(){/* stuff */})ทำอย่างไร?
Jasper

คำตอบ:


121

สำหรับ PHP7: ดูคำตอบของ Yasuo Ohgaki :(function() {echo 'Hi';})();

สำหรับเวอร์ชันก่อนหน้า: วิธีเดียวที่จะดำเนินการได้ทันทีที่ฉันคิดได้คือ

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

12
เว้นแต่ (หรือจนกว่า) จะมีการแนะนำฟังก์ชันการเรียกสายโซ่นี่ก็เป็นคำแนะนำของฉันเช่นกัน
เกลือ

2
@ Gordon: php 5.4 ยังไม่มีอะไร?
ไดนามิก

@ yes123 ไม่. ยังคงต้องใช้call_user_func
Gordon

2
@BennettMcElwee ลองใช้วิธีนี้: แม้ว่าสิ่งนี้จะทำงานค่อนข้างช้ากว่าทางเลือกที่กำหนด - กำหนดสาย แต่ความเป็นไปได้ที่สิ่งนี้จะทำให้เกิดปัญหาคอขวดที่สำคัญในแอปพลิเคชันของคุณนั้นต่ำมาก เมื่อมีข้อสงสัยเกี่ยวกับโปรไฟล์แอปของคุณภายใต้สภาวะโลกแห่งความเป็นจริง
Gordon

ขอบคุณ @Gordon นั่นคือสิ่งที่ฉันคิด ฉันรู้สึกว่า salathe และ yes123 ไม่พอใจกับวิธีนี้และฉันก็สงสัยว่าทำไม ดูเหมือนจะดีสำหรับฉัน
Bennett McElwee

28

ในPHP 7คือการทำเช่นเดียวกันในจาวาสคริปต์

$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 () ได้เช่นกันในส่วนอื่น ๆ ของโค้ด ฟังก์ชันเรียกใช้งานทันทีทำให้ชัดเจนว่าไม่ควรรันโค้ดนี้ซ้ำสอง
Daniel Howard

3
พวกเขาไม่สามารถเรียกrunใช้ฟังก์ชันของคุณในส่วนอื่น ๆ ของโค้ดได้เนื่องจากไม่มีหมายเลขอ้างอิงสำหรับฟังก์ชันของคุณที่มีอยู่หลังบรรทัดซึ่งเรียกใช้งานทันที
Pacerier

3
@DanielHoward ประเด็นrun()คือการเรียกใช้ฟังก์ชันที่ไม่มีชื่อส่งผ่านไปยังมันทันที เช่นเดียวกับcall_user_func()ไม่มีการส่งผ่านพารามิเตอร์
Cypher

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
คำตอบที่ดี แต่ทำไมคุณถึงจัดรูปแบบเป็นการดำเนินการบรรทัดคำสั่ง?
Kodos Johnson

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

6
คุณสามารถให้รายละเอียดเพิ่มเติมได้หรือไม่? อาจจะเพิ่มคำอธิบาย?
MoralCode

2

หมายเหตุคำตอบที่ยอมรับนั้นใช้ได้ แต่ใช้เวลานานถึง 1.41 เท่า (ช้ากว่า 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.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.