[英]Intercepting calls to methods in PHP
I have a class with static methods, and I would like to intercept method calls before the methods are called. 我有一个静态方法的类,我想在调用方法之前拦截方法调用。
So if I call 所以,如果我打电话
$model = DataMapper::getById(12345);
then I want some method in DataMapper to be called before this method is called, and then optionally this intercepting method can subsequently call self::getById(12345). 然后我希望在调用此方法之前调用DataMapper中的某个方法,然后可选地,此拦截方法可以随后调用self :: getById(12345)。 Is there a way to do this? 有没有办法做到这一点?
I am implementing Memcache on my server, so that is why I want to intercept method calls. 我正在我的服务器上实现Memcache,所以这就是我想拦截方法调用的原因。 I don't want the static methods to query the database if models are already cached, and I also don't want to have to modify hundreds of different mapper methods, redundantly, to support memcache. 如果模型已经被缓存,我不希望静态方法查询数据库,我也不想冗余地修改数百种不同的映射器方法来支持memcache。
I am running PHP 5.2.6. 我正在运行PHP 5.2.6。
This'd do the job: Triggering __call() in PHP even when method exists 这样做: 即使方法存在,也在PHP中触发__call()
Just declare your static methods as protected
so they're inaccessible outside the class and get the __callStatic()
magic method to invoke them. 只需将静态方法声明为protected
这样它们就无法在类外部访问,并获得__callStatic()
魔术方法来调用它们。
Edit: oops, you'll be needing 5.3 to do it... 编辑:哎呀,你需要5.3来做...
This is one example where you might want to consider ditching static methods in favor of polymorphism. 这是一个您可能想要考虑抛弃静态方法以支持多态的示例。 If your data-mapper was an interface then you could have two implementations, one for the database and one for memcache: 如果你的数据映射器是一个接口,那么你可以有两个实现,一个用于数据库,一个用于memcache:
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
}
I just came up with a way to intercept method calls in PHP - Check it out . 我想出了一种方法来拦截PHP中的方法调用 - 检查出来 。
It's just a basic example, and classes that want to be interceptible have to "opt in" - you can't interfere with the behavior of classes that don't implement the two magic methods. 这只是一个基本的例子,想要易受影响的类必须“选择加入” - 你不能干扰那些没有实现两种魔术方法的类的行为。
I don't know if this meets your needs - but this pattern can be implemented without code generation or runtime bytecode hacks, and that's gotta be a plus ;-) 我不知道这是否符合您的需求 - 但这种模式可以在没有代码生成或运行时字节码黑客的情况下实现,而且这是一个加分;-)
I guess you could have created some magic with runkit , but you would need to compile the extension from cvs, since the latest version does not support 5.2.x 我想你可以用runkit创建一些魔法,但你需要从cvs编译扩展,因为最新版本不支持5.2.x
Example: 例:
<?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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.