【问题标题】:Making a method in PHP automatically run some code after being called. Possible?使 PHP 中的方法在被调用后自动运行一些代码。可能的?
【发布时间】:2012-03-11 02:11:40
【问题描述】:

我不确定我要找的东西是否有名字,所以我搜索起来有点困难,所以如果我所问的问题之前已经在这里得到了回答,我深表歉意。

情况是我有一个抽象类,当然还有许多其他类扩展它。

抽象类中的抽象方法称为run(),所有的扩展类都定义了这个方法。

我的问题是我想在调用run()方法后调用一些通用代码,但是我想知道是否有更好的方法来做到这一点。

我当然可以将我的通用代码粘贴到每个扩展类的 run() 方法中,但如果我这样做,那么从那时起进行简单的更改对我来说将是很多工作。

我也可以将我的通用代码放入父类中的一个方法中,然后从扩展类的run() 方法中使用$this 调用if。

但我的问题是,有没有更好的方法来做到这一点,还是我必须使用 $this 关键字或将代码粘贴到每个类的代码中?

下面是一个小例子,说明我想用我当前的想法做什么:

abstract class Parent_Class {
    public abstract function run();

    protected function common_code() {
        // Common code here
    }
}

class Child_Class {
    public function run() {
        // Code here
        // I want some common code to run after the run method has been called

        $this->common_code(); // Is this the best way to do it?
    }
}

或者是否有可能以某种方式告诉类,何时调用 run() 方法以自动运行 common_code() 方法?

【问题讨论】:

    标签: php class methods automation


    【解决方案1】:

    更简单的方法是使用第三种方法,它调用run(),然后调用common_code()。然后子类可以随意覆盖run()

    abstract class Parent_Class {
        public abstract function run();
    
        protected function common_code() {
            // Common code here
        }
    
        protected function start() {
            $this->run();
            $this->common_code();
        }
    
    }
    
    class Child_Class {
        public function run() {
            // Code here
        }
    }
    

    【讨论】:

    • 这是一个非常好的观点 - 我不敢相信我没有想到它......我会把这个问题留得更久,看看是否其他人有不同的建议,但在阅读之后你的答案现在看起来很明显。
    【解决方案2】:

    根据 Bradley Forster 的回答,您可以将方法定义为受保护的,因此当从类外部调用它时,您可以使用 php magic __callmetod 拦截事件,因为

    __call() 在对象上下文中调用不可访问的方法时触发。

    然后您可以从 __call 函数执行该方法

    class A {
    
      public function __call($method, $args){
    
         if(!method_exists($this, $method))
           throw new Exception("Call to undefined method ".__CLASS__."::$method()");
    
         echo "doing something BEFORE function 'run' execution\n";
    
         $retval = call_user_func_array(array($this, $method), $args);
    
         echo "doing something AFTER function 'run' execution\n";
    
         return $retval;
      }
    
      protected function run() {
          echo "function 'run' executed\n" ;
      }
    }
    
    $a = new A;
    $a->run();
    

    【讨论】:

      【解决方案3】:

      Amber 给出的答案很好很简单。但要求您将数据放入run() 但调用start()。这是一个替代方案,它允许您在所有脚本中使用您的代码 $a->run(),并在您的公共代码中使用 $a->run(),但封装在命名空间中。

      文件 hooks.php

      <?php
      // File: hooks.php
      namespace hook;
      
      class processHooks {
          public function __construct() { /* Fatal Error without constructor */ }
      
          protected function processHooks($_c, $method, $args) {
              /* Swap the next two callbacks to run your custom code after */
              call_user_func_array("\hook\\{$_c}::{$method}", $args);
              return call_user_func_array(array($_c,$method), $args);
          }
      }
      
      class A {
          public function foo() {
              echo 'Doing code stuff BEFORE calling child function....<br>';
          }
      }
      

      文件regular_file.php

      <?php
      // File: regular_file.php
      include "hooks.php";
      
      class A extends \hook\processHooks {
      
          /* All that is required is this function
           * and the function with common code to be protected
           */
          public function __call($method, $args) {
              self::processHooks(__CLASS__, $method, $args);
          }
      
          protected function foo() {
              echo 'Method is called....<br>';
          }
      }
      
      $a = new A();
      $a->foo();
      

      这是因为 regular_file.php 中类 A 的方法 foo 是受保护的,所以它不能在类外调用,所以调用它触发 PHP 魔法方法__call

      __call() 在对象上下文中调用不可访问的方法时触发。

      【讨论】:

      • 这是我使用所有静态函数设计的系统的简化版本。如果您想使用它,可以很容易地改回来。
      猜你喜欢
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 2013-05-09
      相关资源
      最近更新 更多