2012-04-04 36 views
12

xem xét lớp này:PHP làm thế nào để tránh đệ quy vô hạn ở đây?

class test 
{ 
    public function __set($n, $v) 
    { 
     echo "__set() called\n"; 
     $this->other_set($n, $v, true); 
    } 

    public function other_set($name, $value) 
    { 
     echo "other_set() called\n";  
     $this->$name = $value; 
    } 

    public function t() 
    { 
     $this->t = true; 
    } 
} 

Tôi đang quá tải __set() magic method của PHP. Bất cứ khi nào tôi đặt một thuộc tính trong một đối tượng của lớp test, nó sẽ gọi __set(), mà lần lượt gọi other_set().

$obj = new test; 
$test->prop = 10; 

/* prints the following */ 
__set() called 
other_set() called 

Nhưng other_set() có dòng sau $this->$name = $value. Không nên kết quả này trong một cuộc gọi đến __set(), gây ra đệ quy vô hạn?

Tôi đã giả định rằng nó sẽ gọi __set() chỉ khi đặt mọi thứ bên ngoài lớp học. Nhưng nếu bạn gọi phương thức t(), bạn có thể thấy nó rõ ràng cũng đi qua __set().

Trả lời

11

__set is only called once per attempt for a given property name. Nếu nó (hoặc bất cứ điều gì nó gọi) cố gắng đặt cùng một thuộc tính, PHP sẽ không gọi lại __set - nó sẽ chỉ đặt thuộc tính trên đối tượng.

+0

Điều này là chính xác. Nếu bất cứ ai muốn xem chi tiết triển khai, nó nằm trong 'zend_object_handlers.c'. – Confluence

+0

@Confluence: Cảm ơn ... tôi đã tự hỏi tôi đã đọc ở đâu. :) Không thể tìm thấy nó trong hướng dẫn sử dụng; tôi đã bắt đầu tự hỏi nếu tôi tưởng tượng nó. Nhưng tất cả các bài kiểm tra của tôi đã xác nhận nó, vì vậy ... – cHao

+0

Câu trả lời này rất hữu ích! –

2

Từ documentation:

__set() được chạy khi ghi dữ liệu vào không thể tiếp cận tính

Ví dụ:

class foo { 
    private $attributes; 
    public $bar; 

    public function __construct() { 
    $this->attributes = array(); 
    } 

    public function __set($n, $v) { 
    echo "__set() called\n"; 
    $this->attributes[$n] = $v; 
    } 
} 

$x = new foo; 
$x->prop = "value"; 
$x->attributes = "value"; 
$x->bar = "hello world"; 

Trong trường hợp này, $x->prop là không thể tiếp cận và __set sẽ được gọi. $x->attributes cũng không thể truy cập được, vì vậy __set sẽ được gọi. Tuy nhiên, $x->bar có thể truy cập công khai, do đó, __set sẽ không được gọi là.

Tương tự, trong phương thức __set, $this->attribtues có thể truy cập được, do đó không có đệ quy nào.

Trong mã ví dụ của bạn ở trên, $this->$name có thể truy cập được trong phạm vi được gọi, do đó __set không được gọi.

+0

Sự khác biệt là gì? – Confluence

+0

@Confluence tài sản không thể truy cập từ bên trong lớp chính nó .. – TZHX

+0

@TZHX Không thể truy cập có thể có nghĩa là không hiển thị HOẶC không khai báo. Tất cả các thuộc tính đều không thể truy cập được theo định nghĩa vì tôi không có thuộc tính được khai báo. – Confluence

Các vấn đề liên quan