This is the first of several posts I plan to write about the Lithium framework. As a brief introduction, Lithium is a PHP framework written from the ground up to take full advantage of features new to PHP 5.3. If you want to find out more, you can view the project on Github
A unique feature of Lithium is its method filter system. To summarize, it allows for intercepting method calls as well as modifying arguments and return values. This not only makes for some interesting ways to extend the framework but also helps maintain better separation of cross-cutting concerns.
At it’s core, Lithium provides two base classes that provide an
applyFilter method to any sub classes.
lithium\core\Object (for non static classes)
lithium\core\StaticObject (for static classes)
These classes are used throughout the framework but are also available for use in application and library code.
Make a Method Filterable
To start, we have a simple
calculate method. Nothing fancy… just some basic multiplication to calculate a total.
Now, a refactored version to make it filterable.
What’s going on here?
Method filtering works by creating a chain of functions that will be executed upon calling a method. To make a method filterable, you need add it to a corresponding filter chain (using the name of the original method). The call to
static::_filter is doing just that. The
_filter method takes the method name, array of arguments to pass to each filter in the chain and a function that represents the current method. Note that the body of the original
calculate method is now inside the filter function. In short, this code is adding the
calculate function to the end of the filter chain.
Now, any calls to
PriceCalculate::calculate will first apply any filters before calling the final method in the chain.
Applying a Filter
To make the above code changes more useful, we’ll look at applying a filter to the
For the sake of example, let’s say that we need to charge an additional $10 for the month of June… for whatever reason. We can easily apply a filter that will handle this logic.
This is where things get a bit more interesting. In the filter, there is access to the arguments that were passed to the
calculate method as well as access to the return value of the original method.
Each filter receives a reference to the filter chain and allows for control over when the next filter is executed. Of course, it also offers the ability to simply stop execution of the chain all together. By not calling the
next method on the chain, you’re effectively replacing the method with your filter.
Lithium uses filters throughout its core for things like content negotiation, error handling, logging and more. For further info, take a look at The Lithium Filters Guide