Explore Aspect Oriented Programming with CodeIgniter, Part 2
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 calledpost_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