2009-10-08 25 views
9

tình hình của tôi là mô tả tốt nhất với một chút mã:PHP trên lớp con

class Foo { 
    function bar() { 
     echo "called Foo::bar()"; 
    } 
} 

class SubFoo extends Foo { 
    function __call($func) { 
     if ($func == "bar") { 
      echo "intercepted bar()!"; 
     } 
    } 
} 

$subFoo = new SubFoo(); 

// what actually happens: 
$subFoo->bar(); // "called Foo:bar()" 

// what would be nice: 
$subFoo->bar(); // "intercepted bar()!" 

Tôi biết tôi có thể có được điều này để làm việc bằng cách xác định lại bar() (và tất cả các phương pháp khác có liên quan) trong tiểu lớp học, nhưng với mục đích của tôi, nó sẽ được tốt đẹp nếu chức năng __call có thể xử lý chúng. Nó chỉ làm cho mọi thứ trở thành một chỗ ngồi và dễ quản lý hơn.

Điều này có thể thực hiện được trong PHP không?

Trả lời

13

__call() chỉ được gọi khi chức năng không được tìm thấy sao cho ví dụ của bạn, như được viết, là không thể.

2

Nó không thể được thực hiện trực tiếp, nhưng đây là một sự thay thế tốt:

class SubFoo { // does not extend 
    function __construct() { 
     $this->__foo = new Foo; // sub-object instead 
    } 
    function __call($func, $args) { 
     echo "intercepted $func()!\n"; 
     call_user_func_array(array($this->__foo, $func), $args); 
    } 
} 

loại này điều là tốt để gỡ lỗi và thử nghiệm, nhưng bạn muốn tránh __call() và bạn bè càng nhiều càng tốt trong mã sản xuất vì chúng không hiệu quả lắm.

+0

Điều này. Bạn cần phải làm theo các mô hình mặt tiền. Có một lớp bao bọc mà "sở hữu" đối tượng bạn muốn ghi đè lên tất cả các chức năng này. Sử dụng __call() để truyền qua các phương thức khi cần, thực hiện thêm bất kỳ công việc nào phù hợp. Đừng đổ mồ hôi hiệu suất trừ khi mã của bạn được gọi liên tục và ứng dụng của bạn bị giới hạn CPU (hầu như không bao giờ là trường hợp) - thời gian lập trình hầu như luôn quan trọng hơn hiệu suất khi quyết định loại giao dịch này. –

0

Nếu bạn cần thêm thứ gì đó thêm vào thanh mẹ(), điều này có thể thực hiện được không?

class SubFoo extends Foo { 
    function bar() { 
     // Do something else first 
     parent::bar(); 
    } 
} 

hoặc đây chỉ là một câu hỏi từ sự tò mò?

+1

vấn đề xuất phát từ thực tế là lớp cha có thể có một đống các hàm, và tôi không muốn sao chép tất cả chúng trong lớp con, chỉ để áp dụng cùng một hành vi ('// làm điều gì khác trước tiên 'một phần) cho tất cả chúng – nickf

+0

@nickf Tuyệt đối, điều này dường như với tôi như một thứ gì đó rất cần thiết Tôi không hiểu tại sao nó không có trong PHP. –

0

Những gì bạn có thể làm để có tác dụng tương tự như sau:

<?php 

class hooked{ 

    public $value; 

    function __construct(){ 
     $this->value = "your function"; 
    } 

    // Only called when function does not exist. 
    function __call($name, $arguments){ 

     $reroute = array(
      "rerouted" => "hooked_function" 
     ); 

     // Set the prefix to whatever you like available in function names. 
     $prefix = "_"; 

     // Remove the prefix and check wether the function exists. 
     $function_name = substr($name, strlen($prefix)); 

     if(method_exists($this, $function_name)){ 

      // Handle prefix methods. 
      call_user_func_array(array($this, $function_name), $arguments); 

     }elseif(array_key_exists($name, $reroute)){ 

      if(method_exists($this, $reroute[$name])){ 

       call_user_func_array(array($this, $reroute[$name]), $arguments); 

      }else{ 
       throw new Exception("Function <strong>{$reroute[$name]}</strong> does not exist.\n"); 
      } 

     }else{ 
      throw new Exception("Function <strong>$name</strong> does not exist.\n"); 
     } 

    } 

    function hooked_function($one = "", $two = ""){ 

     echo "{$this->value} $one $two"; 

    } 

} 

$hooked = new hooked(); 

$hooked->_hooked_function("is", "hooked. "); 
// Echo's: "your function is hooked." 
$hooked->rerouted("is", "rerouted."); 
// Echo's: "our function is rerouted." 

?> 
1

Một điều bạn có thể thử là để thiết lập phạm vi chức năng của mình để tư nhân hoặc bảo vệ. Khi một hàm riêng được gọi từ bên ngoài lớp, nó gọi phương thức ma thuật __call và bạn có thể khai thác nó.

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