如何在php类中执行某方法的时候自动执行另一个方法?比如我执行数据插入的时候自动运行数据过滤的方法?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在php类中执行某方法的时候自动执行另一个方法?比如我执行数据插入的时候自动运行数据过滤的方法?相关的知识,希望对你有一定的参考价值。

比如数据插入方法insert();在执行该方法的时候自动进行数据检查方法fileter()?有点类似于条件触发

php没有事件机制。有一些模拟事件的方法,但我觉得代码太繁琐了,不实用。这里我向你推荐PHP的魔术方法。


魔术方法会在调用一个不存在或是非公有的方法之前,自动根据某种规则调用另外一个方法。比如下面的类就是了这样:在调用insert方法时,判断类中是否有before_insert方法。如果有则先调用before_insert方法,并检查它的返回值,决定是否继续调用insert。如果before_insert是一个过滤函数,如果验证失败就会返回false,insert插入就不会进行了。


如果不明白可以阅读PHP手册中介绍魔术方法的部分。

<?php
class MyClass
    // 如果使用类的实例调用$method,但$method方法不是公有的,就会触发此函数。
    public function __call($method, $args) 
        // 检查是否存在方法$method
        if (method_exists($this, $method)) 
            $before_method = 'before_' + $method;
            // 检查是否存在方法$before_method
            if (method_exists($this, $before_method)) 
                // 调用$before_method,检查其返回值,决定是否跳过函数执行
                if (call_user_func_array(array($this, $before_method), $args)) 
                    retrun call_user_func_array(array($this, $method), $args)
                
             else 
                // $before_method不存在,直接执行函数
                retrun call_user_func_array(array($this, $method), $args)
            
         else 
            throw new Exception('no such method ' . $method);
        
    
    
    // 注意这里不要写成public
    private function insert() 
    
    // 低调!不要写出公有的
    private function before_insert() 


$myobj = MyClass;
$myobj->insert('mytable', array('name'=>'2012'));

追问

我试了貌似不行,仍然提示Call to private method User::add() from context 'UserLogin' in C:\wamp\www\new\action\userlogin.php on line 12

追答

上面的代码中有一点笔误,现重新贴一遍。我已经测试过,没有问题。请仔细检查你写的代码。

class MyClass
    // 如果使用类的实例调用$method,但$method方法不是公有的,就会触发此函数。
    public function __call($method, $args) 
        // 检查是否存在方法$method
        if (method_exists($this, $method)) 
            $before_method = 'before_' + $method;
            // 检查是否存在方法$before_method
            if (method_exists($this, $before_method)) 
                // 调用$before_method,检查其返回值,决定是否跳过函数执行
                if (call_user_func_array(array($this, $before_method), $args)) 
                    return call_user_func_array(array($this, $method), $args);
                
             else 
                // $before_method不存在,直接执行函数
                return call_user_func_array(array($this, $method), $args);
            
         else 
            throw new Exception('no such method ' . $method);
        
    


$myobj = new MyClass;
$myobj->insert('mytable', array('name'=>'2012'));

追问

我的add方法在user类里面,user类继承自model类,model类里面有__call方法,在login类里面调用user里的private add方法。目前call方法里面仅写了一句exit(‘;’),但是结果并没有触发call方法

追答// 为了不覆盖父类的方法,可以这样做
public function __call($method, $args)         // 检查是否存在方法$method
        if (method_exists($this, $method)) 
            $before_method = 'before_' + $method;
            // 检查是否存在方法$before_method
            if (method_exists($this, $before_method)) 
                // 调用$before_method,检查其返回值,决定是否跳过函数执行
                if (call_user_func_array(array($this, $before_method), $args)) 
                    return call_user_func_array(array($this, $method), $args);
                
             else 
                // $before_method不存在,直接执行函数
                return call_user_func_array(array($this, $method), $args);
            
         else 
            // 亮点在这里
            parent::__call($method, $args);
        
    

子类的__call方法一定会触发,不受父类是否有__call方法影响。

追问

我把你的代码复制过去运行提示:Fatal error: Call to private method MyClass::insert() from context '' in C:\wamp\www\new\index.php on line 42
是不是我的服务器配置有问题啊

追答

因为行数太多贴不上去,我把insert等函数的定义删除了,注意一下

追问

我加上了的,而我把ADD改成一个不存在的方法名称却可以触发call方法。就private定义的add方法不触发。怪了。

追答

有可能是PHP版本的原因,我不太确定。
你也可以使用一个不存在的方法。你在类中定义一个do_insert方法,让__call来调用这个方法。当然你还是调用insert这个“公有方法”。

参考技术A 在写一个自定义函数,在执行方法的时候$this->自定义函数名 参考技术B 执行该方法的时候调用另一个方法

如何用php作Linux自动执行脚本

参考技术A   Linux中crontab是实现定时执行的指令,利用这个指令我们就可以定时执行某一个php文件,从而实现用PHP做Linux自动执行脚本。
  如何用PHP作Linux自动执行脚本?
  在安装PHP的时候,会产生一个可执行文件,文件名为php.将它 copy 到 /usr/local/bin 下.在终端方式执行php程序:
    php -q onlinnum.php
  PHP 原本是应用在网页应用的﹐因此它会送出 HTML 的HEADER﹐但是在此我们是要将 PHP 用作 Shell Script﹐"-q" 就是表示不要送 出 HEADER 的意思.你可以试试看不加上 -q 的显示结果。此时你已经可以在终端方式下执行PHP 代码了。   linux命令:cron daemon
  这是一个系统中常驻的服务,功能在于执行例行性的工作,如每天一次或每月一 次检查磁盘。cron daemon 会在每分钟检查一次排定的工作表(crontab),看看是否有要执行的指令,所有的输出会以mail寄给用户。
  设置 crontab
  命令:crontab -e
  该命令呼叫vi编辑器来编辑执行的清单。例如
  0 0 1,15 * * fsck /home
  1 * * * * /home/myhome/printhello
  每一行代表一项排定的工作,在指令前为排定的时间,总共有5个栏位,以空格间隔,由左到右依序如下:
  --------------------------
  分钟 从00到 99
  点钟 从0到 24
  日 从01到31
  月 从01到12
  星期 从01到07,代表星期一到星期日
  *号表示"每" ,如每天执行,就在第三栏填*号
  --------------------------
  所以上例的两项工作是:
  每月1号和15号检查/home 磁盘
  每小时的第一分执行 /home/myhome/printhello 这个文件
  查看crontab:crontab -l
  删除crontab:crontab -r
  我们就知道该怎么利用PHP和crontab命令作Linux自动执行脚本了。
  还需要注意什么问题?
  如果php中有使用数据库,如oracle等,执行脚本中还需export Oracle的环境设置。因为cron下的脚本执行的用户都是在没登陆状态下执行的,少了很多系统里设置的环境变量的值,在连接数据库的时候会出问题。

以上是关于如何在php类中执行某方法的时候自动执行另一个方法?比如我执行数据插入的时候自动运行数据过滤的方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何用php作Linux自动执行脚本

PHP通过反射方法调用执行类中的私有方法

如何从另一个类调用执行 segue 方法?

如何从另一个类中调用 onItemClick 方法?

如何用php作Linux自动执行脚本?

PHP 构造方法 __construct()