Explore Aspect Oriented Programming with CodeIgniter, Part 2

This entry is part 2 of 3 in the series Explore Aspect Oriented Programming with CodeIgniter

Explore Aspect Oriented Programming with CodeIgniter

In the previous part of this series we learned what Aspect Oriented Programming (AOP) is and the meaning of important AOP terminology. In this part I’ll explain why we need AOP using practical examples and how to add AOP behavior to your PHP application using the CodeIgniter framework.

Practical Cross-Cutting Concerns

First, let’s take a look at some of the cross-cutting concerns that can be found in almost every web application.

Logging

Logging is one of the most essential functions in a web application since it allows us to trace the code execution flow. When a bug occurs in a live application, we cannot change any code to identify the bugs. Log files are often the only available resource for finding these bugs.

Writing log messages to a file or to the database is the most commonly used method. The information you write to the log may vary depending on the type of application and the logic you’re logging. Some generic points worth capturing are entering into functions, returning from functions, and returning with errors.

<?php
function addPost() {
    $log->writeToLog("Entering addPost");
    // Business Logic
    $log->writeToLog("Leaving addPost");
}

If we think from AOP perspective, the above situation is equal to both before and after advices. Hence around advice would be most suitable for logging.

Authentication and Authorization

Authentication is the process of identifying the validity of a user inside the system. We often use a username and password at a basic level for authentication. Authorization is the procedure of validating access to specific sections in the system. We need to apply both authentication and authorization in many applications.

<?php
function addPost() {
    $authentication->validateAuthentication($user);
    $authorization->validateAccess($user);
    // business logic
}

Authentication and authorization are generally required at the beginning of the business logic. First the user should be logged into the system and then he should have the necessary permission to add posts. These are cross-cutting concerns since they have to be applied to certain set of methods. We would require before advice in the AOP context for Authentication and Authorization.

Transaction Management

Transaction management ensures the consistency and integrity of the data in your database. Consider a situation where you have multiple dependent functions that saves the data to the database inside a single process. If one function fails and the others execute successfully, your database will be corrupted. Hence it’s important use transaction handling in every application.

<?php
function addPost() {
    $tx->beginTransaction();
    try{
        // Business logic
        $tx->commit();
    }
    catch (Exception $e) {
        $tx->rollback();
    }
}

We commit the data when all of the function calls are successfully completed, and have a rollback operation if something fails. In the AOP context, it will be before advice, after advice and after throwing advice respectively. Before and after advices are common in most AOP frameworks. After throwing advice can be found in advanced AOP frameworks.

How AOP Works

AOP is still not popular in the PHP community, but full-featured AOP frameworks are available for languages like JAVA. In AOP we have the core business logic class on one side and aspects on the other side. These aspects can be applied to core classes at compile time or run time. Frameworks like AspectJ applies AOP at compile time. Since PHP is an interpreted language, we don’t have to worry about applying AOP at compile time, and so it makes more sense to apply AOP at runtime.

As you can see, the core logic and cross-cutting concerns are separated using two PHP classes. Then the AOP framework combines both core and aspect classes at runtime and creates a dynamic proxy class. Dynamic classes contain the advice function calls before and after the actual method class.

There are two types of techniques commonly used in combining aspects with core logic: XML-based configuration and annotation-based configuration.

In XML-based configurations, all the AOP rules for applying cross-cutting concerns are documented in a XML file.

In annotation-based configurations, the rules are defined in-line with the actual methods using annotations. We can use a predefined document comment structure to replace annotations in PHP.

Why CodeIgniter

You might be wondering why I chose CodeIgniter to explain AOP since it doesn’t provide any support for AOP functionality. I did so on purpose to create basic AOP functionality from scratch to help you better understand the concepts and process. If I choose a framework with AOP support, then I would only be able to explain the rule structures and how it works. You wouldn’t be able to apply your knowledge to new AOP frameworks since you don’t understand the basics. Since we are creating everything from scratch here, you’ll be able to adapt to any new framework without much hassle, or even create your own AOP framework someday.

CodeIgniter hooks is another reason which prompted me to choose this particular framework. When a method is called you have to create the proxy class. In AOP frameworks this process is not visible and very complex and hard to explain. CodeIgniter hooks allow us to trigger custom code at certain predefined hook points. Using this, we can trigger custom code on each method call and thus execute AOP functionality. I won’t create proxy classes since creating such functionality requires a lots of coding and is beyond the scope of this tutorial.

Using CodeIgniter Hooks

The CodeIgniter website explains that the hooks feature “provides a means to tap into and modify the inner workings of the framework without hacking the core files.” You can enable hooks by setting the enable_hooks parameter in the config file to true.

There are list of predefined hook points available, but I am just going to explain the hooks necessary for our application. They are:

  • pre_controller – called immediately prior to any of your controllers being called
  • post_controller – called immediately after your controller is fully executed

Let’s setup a hook to call custom code.

<?php
$hook["pre_controller"] = array(
    "class"    => "AOPCodeigniter", 
    "function" => "applyBeforeAspects", 
    "filename" => "AOPCodeigniter.php", 
    "filepath" => "hooks"
);

Place the above code in the hooks.php file in the config directory. Then create the AOPCodeigniter class in the application/hooks folder. Now each time a request is made, the class’ applyBeforeAspects() method will be called before the actual controller method. This is will enable us to combine before advices with core logic (in an actual AOP framework, this will be done using the proxy class).

We can use the following code to apply after advices in the same manner as the above code:

<?php
$hook["post_controller"] = array(
    "class"    => "AOPCodeigniter", 
    "function" => "applyAfterAspects", 
    "filename" => "AOPCodeigniter.php", 
    "filepath" => "hooks"
);

Summary

In this part of the series we’ve learned how to identify where AOP can be used considering practical scenarios of real projects, and I have introduced CodeIgniter as a context for creating basic AOP functionality. Now that we have completed the theoretical sections, in the next part I’ll show you how to use both XML and annotation-based methods to create your own rules structures and how to process those rules to apply advices.

Image via Fotolia

Explore Aspect Oriented Programming with CodeIgniter

<< Explore Aspect Oriented Programming with CodeIgniter, Part 1Explore Aspect Oriented Programming with CodeIgniter, Part 3 >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://zenshadow.com Trevor Geene

    Another great article. I have to admit some of it is a little over my head due to lack of necessity so far in my career, but this is giving me a lot of food for thought on future project that I will face. Looking forward to part 3.

  • http://github.com/dublinan Andre Dublin

    Instead of using hooks, couldn’t we use a Parent Model or Controller that has a method which accepts the name of the class and method we want to instantiate and call?
    Example
    class BASE_Model extends CI_Model
    {
    public function join_point($class, $method, $data)
    {
    $join_class = new $class();
    $joins_class->$method($data);
    }
    }

    class Child_model extends BASE_Model
    {
    $data = 'Hey log me!';
    $this->join_point('aop_model', 'log', $data);
    }

    class AOP_model extends BASE_Model
    {
    public function log($data)
    {
    echo $data;
    }
    }

    • http://github.com/dublinan Andre Dublin

      And it would be probably better to pass the called class by reference as it is done in the system/core/codeigniter.php file when it loads the Hook class
      ie.
      $join_class =& new $class();
      or use the common.php method
      load_class($class);
      https://github.com/dublinan/CodeIgniter/blob/2.1-stable/system/core/Common.php line 121
      https://github.com/dublinan/CodeIgniter/blob/2.1-stable/system/core/CodeIgniter.php line 121

    • http://www.innovativephp.com Rakhitha Nimesh

      You can use something like the above code without using hooks. But how can we define the rules for applying cross cutting concerns. Which methods to apply rules which method not to apply rules.

      Can you please explain further.

      • http://github.com/dublinan Andre Dublin

        Ah, I understand what you mean by defining the rules. My approach seems to be more arbitrary. However in the previous article it, I may have misread it, but the advices looked as if they were arbitrarily set. However they do follow some terminology to establish their placement in the software life cycle. If my method seems to break the rules, please tell me what I’m missing here :)

        • http://www.innovativephp.com Rakhitha Nimesh

          In your code you have included the log method call directly inside the class. Is it going to be inside the constructer or specific function. Not clear about the code. Please explain.

          Actually the rules will be disscussed on the final part of this tutorial series. Once it is published you can provide your way of doing that and we can continue the disscussion :)

          Thanks

          • http://github.com/dublinan Andre Dublin

            Excellent I look forward to the third installment.

  • Alex Gervasio

    Hey Rakhitha,
    I really enjoyed this second post on AOP. Nice work indeed. While I have to admit I’m not a strong advocator of CI, the examples using hooks do make a pretty valid point, as they show in a pretty clear fashion how to keep classes doing just what they meant to be, while keeping all the aspect-related implementation neatly separated, hence adhering to the SRP commandments.
    Just for “further reading”, FLOW3 http://flow3.typo3.org/documentation/guide/partiii/aspectorientedprogramming.html is perhaps the only full-stacked PHP framework with a pretty solid AOP implementation currently running behind the scenes. Not only it packages all the AOP shebang, but combines it in a fairly seamless fashion with OOP and the nuts and bolts of Domain Driven Design.

    • http://www.innovativephp.com Rakhitha Nimesh

      Hello Alex
      Thanks for the comment. Feels great to get such comment on my article from an expert like you.

      Codeigniter may not be the most optimized way of using AOP functionality. But I think it will help the beginners to get familiarize with basics of AOP. I hope they understand the concept as well.

      I haven’t had the chance to use the features of FLOW3 framework yet. I have heard that its the best available at the moment for AOP functionality. Looking forward to learning FLOW3 soon.