2009-09-03 99 views
5

我有一个静态方法的类,我想在方法调用之前拦截方法调用。拦截PHP中的方法调用

所以,如果我叫

$model = DataMapper::getById(12345); 

然后我想在调用此方法之前被称为在DataMapper的一些方法,然后有选择地拦截此方法可随后调用self :: getById(12345)。有没有办法做到这一点?

我正在我的服务器上实现Memcache,所以这就是为什么我想拦截方法调用。我不希望静态方法查询数据库是否已经缓存了模型,并且我也不想修改数百个不同的映射器方法,冗余地支持memcache。

我正在运行PHP 5.2.6。

回答

1

This'd做的工作: Triggering __call() in PHP even when method exists

只是声明你的静态方法为protected所以他们无法进入外班并获得__callStatic()魔术方法来调用它们。

编辑:哎呀,你会需要5.3做...

+0

啊,没事。我忘了我已经问过这个完全相同的问题。 *鸭子*谢谢。 – 2009-09-03 20:24:15

+0

哈哈,哦,哇......我甚至没有注意到你是。具有讽刺意味的。 – brianreavis 2009-09-03 20:30:48

0

我想你可以创建一些魔术runkit,但你需要编译从CVS的延长,因为最新版本不支持5.2.x

例子:

<?php 

/* Orig code */ 
class DataMapper { 
    static public function getById($value) { 
    echo "I'm " . __CLASS__ . "\n"; 
    } 
} 


/* New Cache Mapper */ 
class DataMapper_Cache { 
    static public function getById($value) { 
    echo "I'm " . __CLASS__ . "\n"; 
    } 
} 


// Running before rename and adopt 
DataMapper::getById(12345); 

// Do the renaming and adopt 
runkit_method_rename('DataMapper', 'getById', 'getById_old'); 
runkit_class_adopt('DataMapper','DataMapper_Cache'); 

// Run the same code.. 
DataMapper::getById(12345); 

?> 

Output: 
    I'm DataMapper 
    I'm DataMapper_Cache 
+0

那么,这只是另一个PHP扩展?如果我以这种方式使用runkit,会受到怎样的性能影响? – 2009-09-04 16:56:06

+0

查看示例添加到我的答案... – goddva 2009-09-04 19:14:57

+0

我还没有看到任何速度性能问题 - 但是,我没有任何生产runkit代码..你应该使用runkit的情况下,你没有任何选择.. :) – goddva 2009-09-04 19:16:42

1

这是一个例子,你可能要考虑开沟赞成多态性的静态方法。如果您的数据映射器是一个接口,那么你可以有两种实现方式,一个数据库,一个用于内存缓存:

interface DataMapper { 
    public function getById($id); 
    // other data mapper methods 
} 

class DataMapper_DB implements DataMapper { 

    public function getById($id) { 
     // retrieve from db 
    } 
    // other methods 
} 

class DataMapper_Memcache implements DataMapper { 

    private $db;   

    public function __construct(DataMapper_DB $db, $host, ...) { 
     $this->db = $db; 
     // other set up 
    } 

    public function getById($id) { 

     // if in memcache return that 

     // else 
     $record = $this->db->getById($id); 

     // add record to memcache 

     return $record 
    } 
    //other methods 
} 
1

我只是想出了一个办法拦截在PHP中的方法调用 - Check it out

这只是一个基本的例子,想要被感知的类必须“加入” - 你不能干涉没有实现两种魔法方法的类的行为。

我不知道这是否符合您的需求 - 但可以在不生成代码或运行时字节码的黑客来实现这种模式,那得是一个加;-)