PHP 实际开发需求中使用到 AOP Aspect
前言
什么是AOP,这里不深入,这里主要是阐述AOP中的Aspect(切面),主要是以实际开发中使用到AOP的一个例子来说明比较有深刻的印象。
例如 ThinkPHP 中的控制器前置操作beforeActionList
,又或者中间件,还有自己创建一个基类来实现等等,以上方法在某种意义上也有一些AOP的思想(一般来说 AOP是指将几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为),AOP像OOP一样,只是一种编程范式,AOP并没有规定说,实现AOP协议的代码,要用什么方式去实现。我的理解是 将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程,把和主业务无关的事情,放到代码外面去做,对原有代码毫无入侵性。
AOP可能很多人只是了解过并没有真正使用到实际的项目中,我认为只有在实际项目中去实现才算是有意义的(最好先在个人项目中实践一下)
实践
环境
网关中某个服务使用了hyperf 2.0
需求
有分页的数据中将Laravel
分页器的结果元数据字段转为网关分页规范数据字段
这个的需求有很多方法实现,这里我使用了将 提供分页数据的控制器中的方法 统一进行切面处理,这样的做法,对原有代码毫无入侵性,这就是AOP的好处了,把和主业务无关的事情,放到代码外面去做
Laravel 分页器默认字段
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"first_page_url": "http://laravel.app?page=1",
"last_page_url": "http://laravel.app?page=4",
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"path": "http://laravel.app",
"from": 1,
"to": 15,
"data":[
{
// Result Object
},
{
// Result Object
}
]
}
网关分页规范字段
{
"total": 50,
"current_page": 1,
"last_page": 4,
"data":[
{
// Result Object
},
{
// Result Object
}
]
}
具体实现方法
在hyperf 2.0
中使用 Aspect 切面
通过配置要切入的类,这里切入的是面向有分页数据的控制器中的具体方法
例如 TestController::getList
和 Test1Controller::getList
这两个方法提供了分页数据
定义切面(Aspect)
一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点
class PageResultAspect extends AbstractAspect
{
public $classes = [
TestController::class . '::' . 'getList',
Test1Controller::class . '::' . 'getList',
];
public $annotations = [];
public function process(ProceedingJoinPoint $proceedingJoinPoint)
{
// 切面切入后,执行对应的方法会由此来负责
// $proceedingJoinPoint 为连接点,通过该类的 process() 方法调用原方法并获得结果
$result = $proceedingJoinPoint->process();
//将结果进行统一处理
if(isset($result['first_page_url'])) {
unset($result['first_page_url']);
unset($result['last_page_url']);
unset($result['next_page_url']);
unset($result['path']);
unset($result['prev_page_url']);
unset($result['per_page']);
unset($result['from']);
unset($result['to']);
}
return $result;
}
}
Support Author
本作品采用《CC 协议》,转载必须注明作者和本文链接