การใช้ "$ this" ในฟังก์ชันนิรนามใน PHP ก่อน 5.4.0


86

สถานะคู่มือ PHP

ไม่สามารถใช้$thisจากฟังก์ชันนิรนามก่อน PHP 5.4.0

ในที่ไม่ระบุชื่อหน้าฟังก์ชั่น แต่ฉันพบว่าฉันสามารถทำให้มันทำงานได้โดยการกำหนดให้$thisกับตัวแปรและส่งผ่านตัวแปรไปยังuseคำสั่งที่นิยามฟังก์ชัน

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

นี่เป็นแนวทางปฏิบัติที่ดีหรือไม่?
มีวิธีที่ดีกว่าในการเข้าถึง$thisฟังก์ชันนิรนามโดยใช้ PHP 5.3 หรือไม่?


1
เพียงแค่การประชุมย่อยของฟอรัมโดยปกติแล้วการยอมรับคำตอบจะดีกว่าการแก้ไขคำถามเพื่อให้สอดคล้องกับคำตอบที่คุณต้องการ โดยหลักแล้วคำตอบยังคงมีความหมายอยู่ตลอดเวลา แต่ก็ต้องให้เครดิตสำหรับคำตอบที่ถูกต้องด้วย
แขวนคอ

4
ระวังว่า$CI = $this;และ$CI =& $this; ไม่เหมือนจริง อาจจะเพื่อจุดประสงค์ของคุณ แต่ก็ไม่เหมือนกัน ลองใช้$CI = 'bla'; var_dump($this);ทั้งสองเวอร์ชันเพื่อดูความแตกต่าง
Rudie

1
@Rudie ฉันกำลังเพิ่มเอกสารสำหรับความคิดเห็นของคุณ
นึ่ง

@steampowered มีตัวอย่าง / บทความออนไลน์ดีๆเกี่ยวกับเรื่องนี้ แต่หาไม่เจอ =) ขออภัย เพียงแค่ลองถ้าคุณไม่เห็นความแตกต่าง มันชัดเจนแล้ว
Rudie

คำตอบ:


67

จะล้มเหลวเมื่อคุณพยายามเรียกใช้เมธอดที่ได้รับการป้องกันหรือเป็นส่วนตัวเนื่องจากการใช้วิธีนี้จะนับเป็นการโทรจากภายนอก ไม่มีวิธีแก้ไขสิ่งนี้ใน 5.3 เท่าที่ฉันรู้ แต่มา PHP 5.4 มันจะทำงานได้ตามที่คาดไว้นอกกรอบ:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}
$hello = new Hello();
$helloPrinter = $hello->createClosure();
$helloPrinter(); // outputs "Hello world"

ยิ่งไปกว่านั้นคุณจะสามารถเปลี่ยนสิ่งที่ $ นี้ชี้ไปที่รันไทม์สำหรับฟังก์ชัน anonymus (การปิด rebinding):

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}

class Bye {

    private $message = "Bye world\n";

}

$hello = new Hello();
$helloPrinter = $hello->createClosure();

$bye = new Bye();
$byePrinter = $helloPrinter->bindTo($bye, $bye);
$byePrinter(); // outputs "Bye world"

ได้อย่างมีประสิทธิภาพฟังก์ชั่น Anonymus จะมีbindTo () วิธีการที่พารามิเตอร์แรกสามารถใช้ในการระบุสิ่งที่ $ จุดนี้และการควบคุมพารามิเตอร์ที่สองสิ่งที่ระดับการแสดงผลที่ควรจะเป็น หากคุณไม่ใส่พารามิเตอร์ที่สองการมองเห็นจะเหมือนกับการเรียกจาก "ภายนอก" เช่น สามารถเข้าถึงได้เฉพาะคุณสมบัติสาธารณะเท่านั้น นอกจากนี้ยังให้จดบันทึกทาง bindTo ทำงานก็ไม่ได้ปรับเปลี่ยนฟังก์ชั่นเดิมมันจะกลับมาใหม่


1
ทำเครื่องหมายคำตอบของคุณถูกต้อง แต่เพียงเพื่อชี้แจงสำหรับผู้อ่านอื่น ๆ : $thisการประชุมที่ใช้ในคำถามที่จะทำงานให้วิธีการสาธารณะโดยใช้วัตถุที่มีการอ้างอิง
นึ่ง

5
วิธีการที่ไม่ใช่สาธารณะสามารถเข้าถึงได้โดยใช้การสะท้อนกลับ ไม่มีประสิทธิภาพและชั่วร้ายเล็กน้อย แต่ได้ผล
outis

7

อย่าพึ่งพา PHP ในการส่งผ่านวัตถุโดยการอ้างอิงเสมอไปเมื่อคุณกำหนดการอ้างอิงเองลักษณะการทำงานจะไม่เหมือนกับในภาษา OO ส่วนใหญ่ที่มีการแก้ไขตัวชี้ดั้งเดิม

ตัวอย่างของคุณ:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

ควรจะเป็น:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

หมายเหตุควรกำหนด REFERENCE "&" และ $ CI หลังจากทำการเรียกครั้งสุดท้ายแล้วมิฉะนั้นคุณอาจมีผลลัพธ์ที่คาดเดาไม่ได้อีกครั้งใน PHP การเข้าถึงการอ้างอิงไม่เหมือนกับการเข้าถึงคลาสดั้งเดิมเสมอไปหากเป็นเช่นนั้น

http://php.net/manual/th/language.references.pass.php


6

นั่นเป็นวิธีปกติที่เคยทำ
btw ลองลบ&มันควรจะใช้งานได้โดยไม่ต้องทำเช่นนี้เนื่องจากวัตถุผ่านไปโดยการอ้างอิงใด ๆ


1

ดูเหมือนจะดีถ้าการส่งผ่านข้อมูลอ้างอิงของคุณเป็นวิธีที่ถูกต้องในการทำ หากคุณใช้ PHP 5 คุณไม่จำเป็นต้องมี&สัญลักษณ์มาก่อน$thisเพราะมันจะผ่านการอ้างอิงเสมอโดยไม่คำนึงถึง


2
สหกรณ์จะต้องใช้ 5.3 หรือสูงกว่าเนื่องจาก 4.x ไม่สนับสนุนฟังก์ชั่นที่ไม่ระบุชื่อ :-)
halfer

1

แค่นี้ก็เรียบร้อย ฉันควรคิดว่าคุณสามารถทำได้เช่นกัน:

$CI = $this;

... เนื่องจากการกำหนดที่เกี่ยวข้องกับวัตถุจะคัดลอกการอ้างอิงเสมอไม่ใช่ทั้งวัตถุ

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