2010-06-24 26 views
6

Tôi đã thực hiện một số kiểm tra (để thay thế mã cũ) bằng phương pháp ma thuật __invoke và tôi không chắc đây có phải là lỗi hay không:PHP5.3: Lỗi "Gọi đến không xác định" khi gọi điện từ biến lớp

Hãy giả sử chúng ta có một lớp:

class Calc { 
    function __invoke($a,$b){ 
     return $a*$b; 
    } 
} 

sau đây là khả thi và hoạt động mà không có vấn đề gì:

$c = new Calc; 
$k = $c; 
echo $k(4,5); //outputs 20 

Tuy nhiên nếu tôi muốn có một lớp để lưu trữ một thể hiện của đối tượng đó , này không làm việc:

class Test { 
    public $k; 
    function __construct() { 
     $c = new Calc; 
     $this->k = $c; //Just to show a similar situation than before 
     // $this-k = new Calc; produces the same error. 
    } 
} 

Lỗi này xảy ra khi chúng ta cố gắng gọi nó thích:

$t = new Test; 
echo $t->k(4,5); //Error: Call to undefined method Test::k() 

Tôi biết rằng một "giải pháp" có thể là để có một hàm bên trong thử nghiệm lớp (tên là k) để "chuyển tiếp" cuộc gọi bằng cách sử dụng call_user_func_array nhưng điều đó không phải là thanh lịch.

Tôi cần giữ trường hợp đó trong một lớp chung (cho mục đích thiết kế) và có thể gọi nó là hàm từ các lớp khác ... bất kỳ đề xuất nào?

Cập nhật:

tôi tìm thấy một cái gì đó thú vị (ít nhất là cho mục đích của tôi):

Nếu chúng ta định giá trị "biến lớp học" vào một biến địa phương hoạt động:

$t = new Test; 
$m = $t->k; 
echo $m(4,5); 
+0

Vui lòng cung cấp ví dụ về mã hoàn chỉnh cho biết sự cố của bạn. Mẫu mã bạn nói tác phẩm không hoạt động và mẫu mã bạn nói cho một vấn đề hoạt động. – Sjoerd

+0

Có, xin lỗi, xấu của tôi ... Tôi cập nhật nó. Sjoerd: Ví dụ đó có phù hợp với bạn không? lạ: S – lepe

Trả lời

5

Khi bạn làm $test->k(), PHP cho rằng bạn đang gọi phương thức trên cá thể $test. Vì không có phương thức nào có tên là k(), PHP sẽ đưa ra một ngoại lệ. Những gì bạn đang cố gắng làm là làm cho PHP trả về thuộc tính công khai k và gọi nó, nhưng để làm như vậy bạn phải gán k cho một biến đầu tiên. Đó là vấn đề dereferencing.

Bạn có thể thêm sự kỳ diệu __call phương pháp để lớp Test của bạn để kiểm tra xem có một tài sản với tên phương pháp gọi và gọi mà thay vào đó mặc dù:

public function __call($method, $args) { 
    if(property_exists($this, $method)) { 
     $prop = $this->$method; 
     return $prop(); 
    } 
} 

tôi để lại thêm những lập luận để gọi cho bạn . Bạn cũng có thể muốn kiểm tra xem thuộc tính is_callable.

Nhưng dù sao, sau đó bạn có thể làm

$test->k(); 
+0

Chúng tôi đăng cùng một lúc ... Có thể điều đó có thể giúp ... Nếu tôi không tìm thấy bất kỳ phương án nào khác tốt hơn, tôi sẽ đánh dấu câu trả lời của bạn là tốt. – lepe

6

PHP nghĩ rằng bạn muốn gọi một k phương pháp trên dụ $ t khi bạn làm:

$t->k(4, 5) 

đó là hoàn toàn hợp lý. Bạn có thể sử dụng biến trung gian để gọi đối tượng:

$b = $t->k; 
$b(4, 5); 

Xem thêm bug #50029, mô tả vấn đề của bạn.

+0

+1 để tìm lỗi – Gordon

+0

(+1). Bây giờ nó là nhận được rõ ràng cho tôi. Cảm ơn vi đương link. – lepe

2

Bạn không thể sử dụng cú pháp phương thức (như $ foo-> bar()) để gọi đóng hoặc đối tượng với __invoke, vì động cơ luôn nghĩ đây là cuộc gọi phương thức. Bạn có thể mô phỏng thông qua __call:

function __call($name, $params) { 
    if(is_callable($this->$name)) { 
    call_user_func_array($this->$name, $params); 
    } 
} 

nhưng nó sẽ không hoạt động.

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