Sử dụng `$ this` trong một hàm ẩn danh trong PHP trước 5.4.0


86

Các trạng thái hướng dẫn sử dụng PHP

Không thể sử dụng $thistừ hàm ẩn danh trước PHP 5.4.0

trên trang chức năng ẩn danh . Nhưng tôi thấy rằng tôi có thể làm cho nó hoạt động bằng cách gán $thischo một biến và chuyển biến đó vào một usecâu lệnh tại định nghĩa hàm.

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

Đây có phải là một thực hành tốt?
Có cách nào tốt hơn để truy cập $thisvào bên trong một hàm ẩn danh bằng PHP 5.3 không?


1
Chỉ là một quy ước nhỏ của diễn đàn - thông thường tốt hơn là chấp nhận một câu trả lời hơn là chỉnh sửa một câu hỏi để phản ánh câu trả lời ưa thích của bạn. Điều này chủ yếu là để các câu trả lời vẫn có ý nghĩa vĩnh viễn, nhưng tất nhiên cũng để ghi nhận một câu trả lời đúng.
halfer

4
Hãy coi chừng điều đó $CI = $this;$CI =& $this; không thực sự giống nhau. Có thể vì mục đích của bạn, nhưng chúng không giống nhau. Hãy thử $CI = 'bla'; var_dump($this);với cả hai phiên bản để thấy sự khác biệt.
Rudie

1
@Rudie Tôi đang thêm tài liệu cho nhận xét của bạn
steampowered

@steampowered Có một ví dụ / bài báo hay trên mạng về điều này, nhưng tôi không thể tìm thấy nó =) Xin lỗi. Chỉ cần thử nó nếu bạn không thấy sự khác biệt. Đó là điều hiển nhiên.
Rudie

Câu trả lời:


67

Nó sẽ không thành công khi bạn cố gắng gọi một phương thức được bảo vệ hoặc riêng tư trên nó, bởi vì sử dụng nó theo cách đó được coi là gọi từ bên ngoài. Không có cách nào để giải quyết vấn đề này trong 5.3 theo như tôi biết, nhưng đến với PHP 5.4, nó sẽ hoạt động như mong đợi:

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"

Thậm chí nhiều hơn nữa, bạn sẽ có thể thay đổi $ mà điểm này trỏ đến trong thời gian chạy, đối với các hàm ẩn danh (đóng lại):

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"

Một cách hiệu quả, các hàm ẩn danh sẽ có phương thức bindTo () , nơi tham số đầu tiên có thể được sử dụng để chỉ định $ mà điểm này trỏ tới và tham số thứ hai kiểm soát mức độ hiển thị . Nếu bạn bỏ qua tham số thứ hai, khả năng hiển thị sẽ giống như gọi từ "bên ngoài", ví dụ. chỉ các thuộc tính công cộng mới có thể được truy cập. Ngoài ra, hãy lưu ý về cách bindTo hoạt động, nó không sửa đổi chức năng ban đầu mà trả về một chức năng mới .


1
Đánh dấu câu trả lời của bạn là đúng, nhưng chỉ để làm rõ cho những người đọc khác: quy ước được sử dụng trong câu hỏi sẽ hoạt động đối với các phương thức công khai sử dụng đối tượng đang tham chiếu $this.
steampowered

5
Các phương pháp không công khai có thể được truy cập bằng cách sử dụng phản chiếu. Không hiệu quả và hơi ác, nhưng nó hoạt động.
outis

7

Không phải lúc nào cũng dựa vào PHP để chuyển các đối tượng bằng tham chiếu, khi bạn chỉ định chính một tham chiếu, hành vi không giống như trong hầu hết các ngôn ngữ OO nơi con trỏ gốc được sửa đổi.

ví dụ của bạn:

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

nên là:

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

LƯU Ý THAM KHẢO "&" và $ CI nên được chỉ định sau khi các lệnh gọi cuối cùng trên nó đã được thực hiện, nếu không, bạn có thể có đầu ra không thể đoán trước, trong PHP, truy cập một tham chiếu không phải lúc nào cũng giống như truy cập vào lớp gốc - nếu điều đó hợp lý.

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


6

Đó là cách bình thường mà nó đã được thực hiện.
btw, cố gắng loại bỏ &nó sẽ hoạt động mà không có điều này, vì các đối tượng đi qua ref theo bất kỳ cách nào.


1

Điều đó có vẻ ổn nếu bạn lướt qua tài liệu tham khảo đó là cách chính xác để làm điều đó. Nếu bạn sử dụng PHP 5, bạn không cần &ký hiệu trước đó $thisvì nó sẽ luôn chuyển qua tham chiếu bất kể.


2
OP phải sử dụng 5.3 hoặc cao hơn, kể từ 4.x không hỗ trợ chức năng ẩn danh :-)
halfer

1

Điều này là tốt. Tôi nghĩ bạn cũng có thể làm điều này:

$CI = $this;

... vì các phép gán liên quan đến các đối tượng sẽ luôn sao chép các tham chiếu, không phải toàn bộ các đối tượng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.