Thought I would do a couple of posts on some basic Object Oriented design patterns and examples of their implementation within the Kohana framework. They’re not going to go into any great detail but will hopefully provide a small insight into some of the inner workings of Kohana and enable you to make full use of some of the inherent power these patterns provide.
This article covers the adapter pattern. You can see some of the Kohana system libraries making use of this pattern by checking out the system/libraries directory. Within this directory you will find the drivers folder, for now take a quick look at it and see if you recognise any of the class names, we’ll come back to it later.
The adapter pattern has a simple goal, that of ‘adaption’, that is to translate the interface of one class (or system) to that of another interface which some other class (or system) expects. Within the context of Kohana we are adapting the interface of different systems to fit with the standard Kohana libraries.
For a high level overview of this, take a look at the imaege above
Kohana Session Library
One practical example of this within Kohana is the Session library. Kohana comes as standard with adapters (or drivers as I shall now refer to them) so that the Session library can work seemlessly with cookie, database or cache based storage.
Each one of these solutions has a very different set of native php functions, and even different methodology in terms of achieving the same end result: Writing to a database is very different when compared to creating and storing a cookie, yet somehow the same Session library must work with all of these.
Lets take a look at reading current session data with a couple of different solutions.
Database
// Load the session $query = (//query db here); if ($query->count() === 0) //return nothing // Load the data $data = $query->current()->data; return $data;
Cookie
$data = (string) cookie::get('session-name');
if ($data == '') //return nothing
return $data;
So how do we come up with a class, which can offer all of these different possibilities to our users?
One solution
One relatively basic solution would be to put some inline logic into our Session class, something like the following;
if(//database driver) //database specific read else if (//cookie driver) //cookie specific else if (//cache driver) //cache specific ...
this would certainly work, and would allow us to use the specific code depending on which configured method the user had chosen. The flaw with the above comes to light when we would like to add another method for storing and reading sessions, perhaps one of the currently trendy cloud services? We would need to directly edit the Session library and hunt out each area in which such a logic switch is employed. This would then lead to a very long and complex class, not fun to maintain! So how can we improve this scenario?
Enter the adapter pattern
The problem here is because in the above situation the Session class has intrinsic knowledge of each of the currently available methods, if we could remove these dependencies then we could ‘de-couple’ the session class from each of the individual implementations (the specifics of which, as the author of the Session library, do not interest us).
So instead we build our library against some abstract functions, which are defined elsewhere. We can then delegate the specific implementation of each of these abstract functions to individual implementing classes (our drivers).
$driver = 'database'; //How the data is read no longer interests us $data = $driver->read();
Defining our ‘abstract’ functions
So when creating our Session class we need a way of defining these generic functions against which we build the class, and which each driver must implement; enter the interface.
An interface defines the functions an implementing class must provide. Take a look within the drivers directory, you will see a file named Session and a directory of the same name. The file is the interface of which we just spoke, open it up and take a look at it, within it you can see each of the functions that must be provided by any implementing class. The Session directory then is where all our drivers are stored . .easy!
To recap
Conclusion
Kohana has been written, from the ground up, with clean well architectured code, the benefits of which are two-fold. Firstly you benefit immediately from the existing libraries and helpers bundled with the framework. Secondly, and most importantly, you are encouraged (note encouraged not forced) to write your (inevitable) extensions to the system in a similarly well architectured fashion.
IMO Kohana strikes the perfect balance between an overly ‘nursed’ system (such as Codeignitor) and a well structured set of libraries (such as Zend). As such it facilitates RAD and at the same time provides ample scope for future expansion and custom system add-ons.
As usual all comments greatly appreciated, I hope to have the next article in this mini-series up next week!
/Matt
Welcome to ninjapenguin. Personal blog of Matthew Wells. I'm a web developer from the North West and enjoy working with Kohana, Mootools and Git
Comments
Great article Matthew.
On a side note, I have been thinking of using a similar adapter pattern for larger scale applications (or modules to be more specific). i.e. Ideally the modules would work on Kohana and other PHP frameworks such as CodeIgniter as long as there are drivers written for them.
Well written there! Thank you
Post a comment