jump to navigation

Getting Started with Aspect Oriented Programming (AOP) in PHP July 29, 2014

Posted by Tournas Dimitrios in PHP.
Tags: ,

Smiley Face

The benefits of Object Oriented Programming (OOP) is that it lets us encapsulate – abstract data and functionality away (which is the key for building large systems). We could achieve the same results with other paradigms, but it seems that OOP is especially helpful in this regard. Aspect Oriented Programming (AOP) is a follow-on development to OOP, developed with the intention of solving some of the practical limitations of OOP. The majority of applications a developer writes will contain common functionality that will be shared across the codebase (mailing, logging, caching, debugging, user-notification, security –ACL–, opening a database connection, etc….. ) . Such functionality is generally described as “cross-cutting concerns” because it’s not specifically relevant to any one piece of code where it might be embedded[used]. An example will better illustrate this subject (the following code is meant for illustrative purposes only; any design issues are beside the point) :

namespace MyNamespace\Controllers;

use MyNamespace\Services\Logger;
use MyNamespace\Services\Mailer;
use MyNamespace\Services\Security;
use MyNamespace\Services\AclException;
use MyNamespace\Models\User;

class UserController
     Code truncated

    * @param String $username Name of the new User
    public function createNewUser($username)
        $dateTime = date('l jS \of F Y h:i:s A');
        if (!$this->security->isGranted('Security::ROLE_ADMIN'))
            throw new AclException('Only root can assign new users');

        try {
            $user = new User($username);
        } catch (Exception $e) {
            $this->logger->error('User create error'. $e->getMessage());
            $this->mailer->send('User create error at : '. $dateTime);

            $this->logger->info("User {$username} created at : " . $dateTime);
            $this->mailer->send("User {$username} created at : " . $dateTime);

It is evident from the above code that the main role of the UserManager object is to manage users, but beyond this, UserManager has to borrow services from other objects in order to fulfill its operations. Most likely the same motif can be spotted across many places of our application (ie Logging, Mailing and Acl functionality will be used  by many objects).  The aforementioned motif is considered bad practice because it violates fundamental design principles and will lead to a system that isn’t easily maintainable-extendable over time. Let us identify a few of those violations :

  • SoC (Separation of Concerns) : Our UserManager object is tightly coupled to other objects. Distributing / Reusing the UserManager class into other projects has a dependency which must be taken into account.
  • SOLID : The above motif clearly violates the “O” of SOLID (ie the Open/Close principle). For instance, if for some reason one of those service-objects on which UserManager depends, change its functionality, this will affect UserManager (but also all objects that might use those service-objects). Having the task to update the relevant code throughout the entire system is not pleasant at all🙂

Cross-cutting concerns  tends to increase the complexity of an application. AOP is a way of modularizing cross-cutting concerns much like object-oriented programming is a way of modularizing common concerns.

Describing AOP in one paragraph : 

Imagine a common task (cross-cutting concern) that  is used across different parts of an application (a service that is used by many objects, so to speak). Instead of calling that task through each and every object that might need its services, we are surrounding each of those objects with a decorator which will undertake to call the services of the task (the decorator would essentially intercept the call on behalf of the decorated, so to speak). The decorator can even act in pre-configured time-points on objects it surrounds  (ie before, after and around). This is the scenario that AOP addresses, it provides a way for the cross cutting concerns  to be modularized – to be packaged up separately without polluting the core of the classes.

AOP vocabulary : 

  • aspect : a modularization of a concern (task) that cuts across multiple objects.
  • advice : action taken by an aspect at a particular join point. There are different types of advices (ie before, after, arround)
  • join point :   methods of an object on which  advices are attached.
  • point cut : a regular expression (a rule, so to speak) that asserts whether or not a given join point will trigger the execution of an advice.

AOP has been around for a long time in the Java world and a plethora of other programming languages. As Java is a compiled language, it uses tools ( like JAspect) which intercept the compilation process (Java source code -> compilation process) and do an analysis of the defined aspects. Whenever a set of rules  matches a point-cut , the aspect is weaved directly into the compiled code. Hence, the framework takes care of merging the code parts together.

How does PHP implements AOP ? : 

Unfortunately there is no unified approach in this regard by the PHP community, while some frameworks have native build-in support for AOP (Lithium, Typo3, Flow3), other frameworks don’t have support for it.  A list off a few solutions that I happen to know :

  • AOP-PHP (a PECL extension) : Installing of this extension i reasonably simple, just use : sudo pecl install aop-beta
    The home page of this extension on Github has all you need to get started . Obviously, on shared hosts this solution is just an  unfulfilled wish🙂
  • Lithium framework : All concrete classes inherit from a base class which has a method filter system that allows for intercepting method calls as well as modifying arguments and return values. Method filtering works by creating a chain of functions (by using a closure) that will be executed upon calling a method. Lithium’s filter guide documentation has all you need to get started.
  • Flow3 : This framework took an interesting route for implementing AOP, it introduced an advanced cache system.  Before a class is cached, aspects (cutting-concerns) are embedded into it. For each request, cached classes will be delivered (instead of the original code). The file system is monitored for changes, if a point-cut matches to a rule , the respective aspect is weaved into the appropriate class  and a new commit is done into the cache.
  • JMSAopBundle : A  bundle that adds AOP capabilities to Symfony2
  • Go! AOP PHP (a library) : Although this library takes the same approach as Flow3 (it caches classes), it is the most elegant (IMO) implementation of AOP for PHP. This library doesn’t depend on a pecl extension, hence, standalone codebases as well frameworks can use this library without any obstacle (provided that PHP is of version >5.3) . To be fair, this library has a couple dependencies (for instance, Doctrine Annotation lib) , but that’s not considered an issue because “composer” (the PHP package manager) handles everything behind the scenes.
    Implementing this library into a codebase (standalone or framework) is really simple. Just instantiate  an “aspect kernel object” into the front-controller (or whatever bootstrap process of your codebase) , define an “aspect” (a class that embodies the task we want to be shared) and finally register the aspect into the “aspect kernel object” . Easy, isn’t it?
    Skeleton applications that implement Go-AOP for Laravel , Zend-framework 2 , Symfony2 and Yii can be cloned from Github.

Final thoughts :

Object-oriented programming is a set of logical entities (objects) whose behavior and interactions could be defined in a number of ways (inheritance, encapsulation, abstraction, polymorphism). This approach of software development has certain limitations as to the decomposition of application business logic aspects. A number of approaches have emerged which aimed at overcoming the aforementioned practical limitations. Among them are subject-oriented programming, adaptive programming, composition filters, AOP and many more. AOP is a whole different approach for developing application. It is as different as object oriented programming can be opposed to procedural programming. As we have already pointed out, AOP isolates the cross-cutting concerns and place them outside applications’ business logic.

Keep in mind that although this article just scratched the surface of this topic, many link are pointing to documentation pages where the reader can gain a deeper insight and understanding . That’s it for now, hope you enjoyed the reading. Thanks for your e-visit  :)


No comments yet — be the first.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s