php notes: the application of AOP

  • 2020-05-30 19:46:12
  • OfStack

introduce

Have you heard of Aspect Oriented Programming before? While php doesn't seem to be overused, AOP is widely used in enterprise development. In this article, I will introduce PHP to you.

This article mainly explains the concept of AOP.


What is AOP?

In application development, we often find that we need a lot of functionality, which is often scattered over multiple points in the code, but which actually have nothing to do with the actual business. For example, we need to make sure that the user is in the login state before performing a particular task. We call these special people "cross-cutting concerns". Let's use Wikipedia to understand the definition of" cross-cutting concerns" (horizontal relationship).
In computer science, "cross-cutting concerns" means" aspect (or directional) programming." These relationships do not decompose well from other systems (framework design or some implementations), resulting in code duplication, meaningful dependencies in the system, or both.
Now that you have a basic understanding of "horizontal relationships," let's see what they look like in the code.

Imagine a scenario in which you are the editor of a blog site. You need to log into the site, create posts, validate posts, edit posts, and so on. If you are not logged in, you should go directly to the login screen. To ensure that these behaviors are safe, any of the above operations need to be validated, as shown below.


<?php
class BlogPost extends CI_Controller
{
    public function createPost() {
        if (!Authentication::checkAuthentication()) {
            // redirect to login
        }
        else {
            // proceed
            Messages::notifyAdmin();
        }
    }
    public function approvePost() {
        if (!Authentication::checkAuthentication()) {
            // redirect to login
        }
        else {
            // proceed
        }
    }
    public function editPost() {
        if (!Authentication::checkAuthentication()) {
            // redirect to login
        }
        else {
            // proceed
        }
    }
    public function viewPost() {
        // ...
    }
}

Looking at the code above, you can see that checkAuthentication() is called before each method, because these actions require the user to log in. There is also notifyAdmin() to identify the administrator account so that a new post can be created. See, there's a lot of "duplicate code" and the BlogPost class, which should only be responsible for managing posts. Verification and identification should be separate. We violated the single responsibility principle.

The singleton responsibility principle states that each class should have only singleton responsibilities (tasks), and that the entire responsibility should be encapsulated in a single class. All services should be carefully and evenly distributed according to responsibilities.

So far, we can understand what AOP means. Horizontal aspect relationships are grouped into a class called "facets". The process of separating horizontal aspect relationships from our core code is called Aspect Oriented Programming.

AOP terminology

There are a number of conditions devoted to interpreting the characteristics of AOP. Understanding these conditions will be the key to your successful integration of AOP into your project.
Aspect
Advice
Joinpoint
Pointcut
We've learned what a cut surface (Aspect) is! Now let's figure out what does 1 mean for the other 3 conditions?

Advice (notices)
Advice is used to call Aspect (section), and as the name implies, Advice is used to define what to do in a situation and when to do it. In our previous example, checkAuthentication(what to do) was advice (advice), which in the specified method should be called before (when) the code is executed.


Joinpoint (access point)
Joinpoint is where we created the Advice application. Looking back at the previous code, you will see that I have invoked several functions that are not directly related to the business logic. In createPost(), for example, cross-cutting concerns should occur before the validation logic is executed and after the message is sent to the administrator. These could be access points.

Access points can be placed anywhere in your application code. But Advice can only be placed at certain points, depending on your AOP framework, which I'll discuss later.

Pointcut (point cutting)
Point cutting defines a way to match notifications to certain access points. Although there are only one pair of access points in our example, you can put thousands of access points in your application, and you don't need to apply notifications to all of them. You can bind any access point you think is necessary to the notification.

Suppose we want to notify createPost(),approvePost(), and editPost(), but there is no viewPost(). We use some method to bind these three methods to notifications. We then create an XML file that contains the section details, which contain a regular expression that matches the access point.

Summary: when there is a cross-cutting relationship in our application, we can create a section that applies the notification function to some access points that choose to use point cutting.


AOP notification type

Notification code can be represented in many ways. As I mentioned earlier, these notification codes depend on the framework you're using, but there are some types you need to be familiar with, as follows:
Advance notice
Post return notification
Post throw notification
Around the notice

Advance notice
Use notifications before a specific point in your code - normally a method is called.

So far, I've often written notifications into methods to simplify concepts and to make your code easier to understand. But in the real world, notifications are often not written in methods. There should be a single controller in which each method is contained, and each method is wrapped with the functionality of AOP. This global controller runs throughout the system and is invisible to us.


<?php
class PathController
{
    function controlPaths($className, $funcName) {
        Authentication::checkAuthentication();
        $classObj = new $className();
        $classObj->$funcName();
    }
}

So let's say I have a class here, basically to show you what's actually going on in that class. Suppose that the controlPaths method is the global pointcut in your application, and every method in your application needs to be accessed through this method. In the method above, we call notification checkAuthentication() before executing each method. B: that's the previous notice.



Post return notification
This notification only executes once after the specified function is completed and returns that access point. Consider the following code:


<?php
class PathController
{
    function controlPaths($className, $funcName) {
        $classObj = new $className();
        $classObj->$funcName();
        Database::closeConnection();
    }
}

Copy the code by Ctrl+C. Notice here that when the method is complete, we clean up the database resources. After returning the notification, we call the notification.


Post throw notification
If the function throws an exception during execution, the notification is applied after the exception is thrown. Here, after the exception is thrown, the notification becomes an error.


<?php
class PathController
{
    function controlPaths($className, $funcName) {
        try {
            $classObj = new $className();
            $classObj->$funcName();
        }
        catch (Exception $e) {
            Error::reportError();
        }
    }
}

Around the notice
The fourth type of notification is peripheral notification, which is a combination of pre-notification and post-notification.


 <?php
class PathController
{
    function controlPaths($className, $funcName) {
        Logger::startLog();
        $classObj = new $className();
        $classObj->$funcName();
        Logger::endLog();
    }
}


Related articles: