2012-03-28 143 views
2

这是我的课:PHP类函数包装

class toyota extends car { 
    function drive() { 
    } 
    function break() { 
    } 
} 

class car { 
    function pre() { 
    } 
} 

有什么办法,我可以这样做,当我运行$小车 - >驱动器(),$小车 - >破()(或任何其他功能在丰田),它会调用$ car-> pre()之前调用丰田功能?

+0

阅读在“构造函数”函数上......这可能是你需要的。 – 2012-03-28 04:38:09

+0

你能澄清一下吗?无论何时您创建新对象或任何时候调用$ car方法,我都无法确定是否要运行$ car-> pre()。下面的答案涵盖了两个 - 我只是不知道哪一个模型。 – 2012-03-28 04:42:59

回答

10

是的。您可以使用protected和一些__call魔术:

class toyota extends car { 
    protected function drive() { 
     echo "drive\n"; 
    } 
    protected function dobreak() { 
     echo "break\n"; 
    } 
} 

class car { 
    public function __call($name, $args) 
    { 
     if (method_exists($this, $name)) { 
      $this->pre(); 
      return call_user_func_array(array($this, $name), $args); 
     } 


    } 

    function pre() { 
     echo "pre\n"; 
    } 
} 

$car = new toyota(); 
$car->drive(); 
$car->dobreak(); 

http://ideone.com/SGi1g

+0

这不仅是使用__call(正确方法)的唯一答案,而且它也是唯一一个实际执行一些method_exists检查并实际调用最初调用的方法的方法。做这个! – sberry 2012-03-28 04:46:32

+0

你的意思是私人而不是保护?原因保护仍然可以通过父母和继承可见。 – Patrick 2012-03-28 04:50:30

+0

@sberry,使用method_exists()进行检查会隐藏调用无效方法时收到的默认错误 – Starx 2012-03-28 05:00:03

1

你可以做以下事情,但我不认为这就是你想要的。

class toyota extends car { 
    function drive() { 
     $this->pre(); 
    } 
    function break() { 
     $this->pre(); 
    } 
} 

class car { 
    function pre() { 
    } 
} 

你可能想看看PHP特定的魔术方法。 http://php.net/manual/en/language.oop5.magic.php

-2

只需添加一个constructor,像这样...

class toyota extends car { 
    function __construct() { 
     $this->pre(); 
    } 

    function drive() { 
     echo "drive!"; 
    } 

    function dobreak() { 
     echo "break!"; 
    } 
} 

class car { 
    function pre() { 
     echo "Hello!"; 
    } 
} 

$car = new toyota(); 
$car->drive(); 
$car->dobreak(); 

Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.

break被保留,所以你不应该将其用作函数名称。

+0

我认为他正在寻找一种方法来在函数调用之前运行'pre'方法,而不是在对象初始化时 – blackpla9ue 2012-03-28 04:43:11

+0

回复时我被中断了。我用构造函数更新了我的示例。它仍然在做这项工作。 – Bjoern 2012-03-28 06:24:17

0

这将更好地与魔术方法进行所谓的__call()

public function __call($name, $arguments) 
{ 
    $this -> pre(); 
    return $this -> $name($arguments); 
} 

这是什么方法?它覆盖默认的方法调用,因此可以调用preCall状态。

toyota

class toyota extends car {  

    public function __call($name, $arguments) 
    { 
     $this -> pre(); 
     return call_user_func_array(array($this, $name), $arguments); 
    } 

    function drive() { 
    } 
    function break() { 
    } 
} 
+0

'$ this - > $ name($ arguments)'---将调用所有以数组形式传递的参数。因此'$ car-> drive(1,2)'将会被'$ car-> drive(array(1,2))'重新调用,这只是不正确的 – zerkms 2012-03-28 07:46:30

+0

@zerkms,你说得对。更新 – Starx 2012-03-28 08:00:39

0

如果你正在使用PHP5(> = 5.3.2),存在与声明的所有方法为私有有效的解决方案。这将强制方法调用从一个函数调用:

exec_method() 

运行在:http://ideone.com/cvfCXm

的代码片段是在这里:

<?php 

    class car { 

     //method to get class method 
     public function get_method($method_name) { 
      $class = new ReflectionClass(get_class($this)); 
      $method = $class->getMethod($method_name); 
      $method->setAccessible(true); 
      return $method; 
     } 

     public function exec_method($method_name, $arg_args=array()) { 

      //execute the pre() function before the specified method 
      $this->pre(); 

      //execute the specified method 
      $this->get_method($method_name)->invokeArgs($this, $arg_args); 
     } 

     public function pre() { 
      echo 'pre'; 
      echo '<br />'; 
     } 
    } 

    class toyota extends car { 
     private function drive() { 
      echo 'drive'; 
      echo '<br />'; 
     } 

     private function brake() { 
      echo 'brake'; 
      echo '<br />'; 
     } 
    } 

    $toyota = new toyota(); 
    $toyota->exec_method('drive'); 
    $toyota->exec_method('brake'); 
?> 

参考:

Answer to Best practices to test protected methods with PHPUnit [closed]