PHP AOP教程案例

下面我将为您详细讲解“PHP AOP教程案例”的完整攻略。

什么是AOP

面向切面编程(Aspect-Oriented Programming, AOP)是一种编程思想,它解决了面向对象编程中的一些横向关注点问题。 AOP 的一个核心功能便是拦截、修改某个对象的某个方法。PHP 的 AOP 有很多库可以使用,这里介绍的是 goaop/aop

安装

使用 composer 安装:

composer require goaop/framework

使用方式

定义切面

切面就是拦截修改某个类的某个方法。我们通过 Annotation 的方式来定义一个切面。例如:

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Around;

class LoggerAspect implements Aspect
{
    /**
     * @param MethodInvocation $invocation Invocation
     *
     * @Around("@execution(MyProject\Annotation\Loggable)")
     */
    public function aroundMethodExecution(MethodInvocation $invocation)
    {
        $method = $invocation->getMethod()->name;
        echo "Before {$method}\n";
        $result = $invocation->proceed();
        echo "After {$method}\n";
        return $result;
    }
}
  1. 类实现了 Go\Aop\Aspect 接口;
  2. 利用 Go\Lang\Annotation\Around 注解来定义切面的类型以及需要修改的方法;
  3. @execution(MyProject\Annotation\Loggable) 表示被 @Loggable 注解的方法将会被拦截修改。

这个切面的作用是在被 @Loggable 注解的方法调用前后分别打印出 "Before" 和 "After" 字符串。

使用切面

利用前文定义的 LoggerAspect 切面,修改 MyController 中的 testAction 方法:

use MyProject\Annotation\Loggable;

class MyController extends Controller
{
    /**
     * @Loggable
     */
    public function testAction()
    {
        return 'Test';
    }
}

testAction 方法上添加 @Loggable 注解后,方法被拦截,进入 LoggerAspectaroundMethodExecution 方法中,打印出对应的日志。

Test:

Before testAction
After testAction

以上就是使用 PHP AOP 的基本流程。

案例演示

这里再举一个常见的案例来说明 AOP 的作用。

问题

假设我们有这样一个场景:我们要在老项目中新增一个接口,需要让这个接口返回的 json 数据,完全按照别的项目返回的 json 数据格式来操作。

但是考虑实际情况,整个老项目中有很多地方都调用到了这个接口,如果我们要在所有这些调用点中修改代码,那就是一件非常麻烦的事情。

那么,那怎样才能让这个接口被调用的时候,能够自动转换 json 数据格式呢?

解决方案

使用 AOP 解决这个问题可以分为以下两个步骤:

  1. 定义转换器:将老项目中的 json 数据转为新的 json 数据;
  2. 编写切面:在老项目中的那个接口方法调用之前,把这个方法返回的 json 数据转换。

第一步:定义转换器

我们需要先定义一个转换器类,实现一个 convert 方法,将老项目中的 json 数据转成新的 json 数据:

class JsonConverter
{
    public function convert($oldJson)
    {
        // 这里是转换逻辑,比如:
        $arr = json_decode($oldJson, true);
        return json_encode($arr, JSON_PRETTY_PRINT);
    }
}

这里我们假设定义了一个 JsonConverter 类来完成 json 转换,实际开发中完全可以根据业务进行相应修改。

第二步:编写切面

在老项目中需要使用 AOP 来切入到接口被调用的方法中,并且在转换 json 数据后保存到返回结果中,这里我们需要编写如下的切面:

class JsonAspect implements Aspect
{
    /**
     * @var JsonConverter $jsonConverter
     */
    private $jsonConverter;

    public function __construct(JsonConverter $jsonConverter)
    {
        $this->jsonConverter = $jsonConverter;
    }

    /**
     * @param MethodInvocation $invocation Invocation
     *
     * @Around("@execution(MyProject\Annotation\JsonSerializable)")
     */
    public function aroundMethodExecution(MethodInvocation $invocation)
    {
        $result = $invocation->proceed();

        // 如果返回的结果是字符串,表示是 json,那么我们就需要处理
        if (is_string($result)) {
            $newJson = $this->jsonConverter->convert($result);
            return $newJson;
        }

        return $result;
    }
}

这里定义了一个名为 JsonAspect 的切面,它的作用是在 @JsonSerializable 注解被使用的接口方法上拦截,获取方法返回结果并将其转换为新的 json 格式。

其中 JsonConverter 是我们在第一步中定义的类,它的实例被传递给了 JsonAspect 切面的构造函数。

示例

现在让我们来看一下一个具体的示例,来模拟刚刚提到的那个场景。

  1. 在老项目中定义一个接口,并且在注解中使用 @JsonSerializable 标记:
class MyController
{
    /**
     * @JsonSerializable
     */
    public function myOldApi()
    {
        return '{"name":"Alice"}';
    }
}
  1. 在切面中实现对这个接口方法返回结果进行转换:
$jsonConverter = new JsonConverter();
$loggerAspect = new JsonAspect($jsonConverter);

$loader = include __DIR__ . '/../vendor/autoload.php';
$annotationLoader = new AnnotationLoader($loader);
$aspectContainer = new AspectContainer();
$aspectContainer->registerAspect($loggerAspect);

$kernel = AspectKernel::getInstance();
$kernel->init([
    'debug' => true,
    'cacheDir' => __DIR__ . '/cache',
    'includePaths' => [
        __DIR__ . '/../src',
        __DIR__ . '/../vendor/goaop/framework/src',
    ],
]);
$kernel->setLoader($annotationLoader);
$kernel->setAspectContainer($aspectContainer);

$controller = new MyController();
$result = $controller->myOldApi();

echo $result;

在上面的代码中,我们初始化 JsonAspect 切面的时候需要传递 JsonConverter 类的实例。然后我们使用 AOP 给 MyController 中的 myOldApi 方法加上了一个切面。当这个方法被调用时,实际返回的结果将会在这个切面中被转换。

以上就是使用 AOP 实现自动修改过滤 json 格式的攻略,希望对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:PHP AOP教程案例 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • PHP超级全局变量、魔术变量和魔术函数汇总整理

    下面是PHP超级全局变量、魔术变量和魔术函数汇总整理的完整攻略。 超级全局变量 超级全局变量是在所有作用域中始终可用的内置变量,在 PHP 脚本的任何部分都可以访问它们。超级全局变量是数组形式,名字前面加上美元符号($),例如$_POST, $_GET, $_SERVER 等。以下是一些常见的超级全局变量: $_POST: 存储通过 HTTP POST 方法…

    PHP 2023年5月27日
    00
  • php中显示数组与对象的实现代码

    让我来为您介绍如何在PHP中显示数组与对象的实现代码。 显示数组的实现代码 如果您想在PHP中显示数组的实现代码,可以使用var_dump函数将数组的内容以及数据类型一起打印出来。示例代码如下: $array = array( "name" => "Jack", "age" => 30,…

    PHP 2023年5月26日
    00
  • php 数组随机取值的简单实例

    首先我们先明确一下问题:如何在 PHP 中随机取出数组中的一个元素。下面是两种解决方法: 方法一:使用 array_rand 函数 array_rand 函数可以随机地从数组中返回一个或多个键名,它的用法如下: //定义一个数组 $arr = array(‘apple’, ‘banana’, ‘orange’, ‘peach’, ‘kiwi’); //使用 …

    PHP 2023年5月26日
    00
  • 微信小程序搜索框样式并实现跳转到搜索页面(小程序搜索功能)

    下面是 “微信小程序搜索框样式并实现跳转到搜索页面(小程序搜索功能)” 的完整攻略: 1. 制作搜索框样式 首先,在小程序页面的wxml文件中,可以添加一个input标签,来实现搜索框的样式。一般情况下,搜索框的样式包含一个输入框和一个搜索按钮,可以像下面这样定义: <view class="search-box"> <…

    PHP 2023年5月23日
    00
  • 百度网盘直链下载助手怎么用?百度网盘直链下载助手安装使用图文教程

    下面就为您详细讲解“百度网盘直链下载助手怎么用?百度网盘直链下载助手安装使用图文教程”的完整攻略。 一、简介 百度网盘直链下载助手是一款Chrome浏览器插件,它可以将百度网盘中的文件转化为直链,方便用户进行下载,同时支持批量转化,大大提升了用户的下载效率。 二、安装 访问Chrome网上应用店:https://chrome.google.com/webst…

    PHP 2023年5月27日
    00
  • uni-app结合PHP实现单用户登陆demo及解析

    接下来我会为你详细讲解“uni-app结合PHP实现单用户登陆demo及解析”的完整攻略。 一、准备工作 在开始编写代码之前,你需要了解以下内容: uni-app框架的使用 PHP语言基础 MySQL数据库的使用 另外,还需要安装以下软件: HBuilderX(uni-app的开发工具) MySQL数据库 Apache或Nginx服务器 二、数据库设计 在开…

    PHP 2023年5月30日
    00
  • destoon二次开发常用数据库操作

    下面是“destoon二次开发常用数据库操作”的完整攻略: destoon二次开发常用数据库操作 在destoon二次开发中,对数据库进行读写操作是非常常见的。本文介绍了destoon常用的数据库操作方法,包括CRUD操作和批量操作。 CRUD操作 CRUD是指应用程序实现的四种基本操作:Create(创建)、Read(读取)、Update(更新)和Dele…

    PHP 2023年5月23日
    00
  • php的ajax简单实例

    下面是PHP的AJAX简单实例的完整攻略。 什么是AJAX? AJAX表示“异步JavaScript和XML”。AJAX不是新技术,而是已经存在一段时间了。它的主要目的是使Web页面具有更快的响应能力。AJAX通过在背景中与服务器进行通信的方式实现这一目的。它允许Web页面更新部分内容而不是整个页面。这意味着用户能够与Web页面进行更快的交互。 如何使用PH…

    PHP 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部