PHP 实际开发需求中使用到 AOP Aspect

PHPHyperfAOP发布于2020-10-11 / 更新于2021-01-02 07:04

前言

什么是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::getListTest1Controller::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;
  }

}
I am a full-stack independent development engineer from China. I love to participate in open source and focus on developing the Web, iOS App & Android App (React Native), desktop applications (Eletron), crawlers, back-end services, system architecture

讨论

暂无评论

目录

1.前言
2.实践
2.1环境
2.2需求
2.2.1Laravel 分页器默认字段
2.2.2网关分页规范字段
.具体实现方法