2009-09-03 137 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

這只是一個基本的例子,想要被感知的類必須「加入」 - 你不能干涉沒有實現兩種魔法方法的類的行爲。

我不知道這是否符合您的需求 - 但可以在不生成代碼或運行時字節碼的黑客來實現這種模式,那得是一個加;-)