代码:
<?php
class DynamicProxy
{
private $obj;
private $regPrePosts=[];
public function __construct($obj)
{
$this->regPrePosts=[];
$this->obj=$obj;
}
public function registerPrePost($type, $obj)
{
if('pre'==$type){
$this->regPrePosts['pre'][]=$obj;
}
else{
$this->regPrePosts['post'][]=$obj;
}
}
public function __call($name, $arguments)
{
// return $this->regPrePosts;
// 使用反射类
$reflection = new ReflectionClass($this->obj);
$method=$reflection->getMethod($name);
// 前置操作
if(isset($this->regPrePosts['pre'])){
echo 'before actions:', PHP_EOL;
foreach ($this->regPrePosts['pre'] as $obj) {
try{
$obj->handle($arguments);
}
catch(\Exception $e){
echo 'error:', $e->getMessage(), PHP_EOL;
return ;
}
}
}
// 执行反射函数
$return=$method->invokeArgs($this->obj, $arguments);
// 后置操作
if(isset($this->regPrePosts['post'])){
echo 'after actions:', PHP_EOL;
foreach ($this->regPrePosts['post'] as $obj) {
$obj->handle($return);
}
}
}
}
// 具体类
class ConcreteClass1
{
public function doOneThing($action_name)
{
echo '* action name:', $action_name, PHP_EOL;
return true;
}
}
// 另一个具体类
class ConcreteClass2
{
public function doAnotherThing($action_name, $token)
{
echo '* another action name:', $action_name, PHP_EOL;
}
}
// 日志类
class Log
{
public function handle($log)
{
echo 'Log:';
print_r($log);
echo PHP_EOL;
}
}
// 认证类
class Auth
{
public function handle($token)
{
if('abc123456'==$token[1]){
echo 'authenticated succeed.', PHP_EOL;
}
else {
// echo 'authenticated faild.', PHP_EOL;
throw new \Exception('authenticated faild.');
}
}
}
// 演示
$DynamicProxy=new DynamicProxy(new ConcreteClass1);
$DynamicProxy->registerPrePost('pre',new Auth);
$DynamicProxy->registerPrePost('pre', new Log);
$DynamicProxy->registerPrePost('post', new Log);
$call=$DynamicProxy->doOneThing('index', 'abc123456');
print_r($call);
echo '--------', PHP_EOL;
$DynamicProxy=new DynamicProxy(new ConcreteClass2);
$DynamicProxy->registerPrePost('pre',new Auth);
$DynamicProxy->doAnotherThing('create', 'abc123456-wrong_token');
示例结果:
before actions:
authenticated succeed.
Log:Array
(
[0] => index
[1] => abc123456
)
* action name:index
after actions:
Log:1
--------
before actions:
error:authenticated faild.