New versions of frameworks are always exciting because they provide more features and can contain important fixes and changes. Go! AOP evolves too, so I prepared this article for users to underline most important changes.
Support for custom streams and read-only file systems
This feature is one of the most interesting, because it allows to use framework with any stream filters and wrappers, for example with phar archives. It is possible to generate an AOP cache and put it into the phar archive as a standalone read-only application. Possible usages of aspects in the phar archives are logging, dry-run control and much more. Do you bored with implementation of dry-run option for each command? Just give a try for AOP and define an aspect for that!
Direct advisors
I received a lot of complains about usage of annotations for defining advices instead of pure PHP code. So I decided to give an alternative way for defining advisors with closures:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
This patch also optimizes injection of advices (interceptors) into the concrete class, so no more slow serialize()/unserialize()
functions, they were replaced by var_export()
and direct injection. I’m also thinking about DSL builders for defining pointcuts in a more natural way:
1 2 3 4 5 6 7 |
|
But this is not included into the current version, please ping me on github if your want it for the next version.
Annotation class filter
PhpDeal Desing by Contract frameworks requires matching of classes based on presence of annotation in the class docblock. This functionality was missed in the framework. Now it’s possible to use special @within(AnnotationClassName)
syntax to match classes that have AnnotationClassName
annotation.
Here is an example of pointcut that intercepts execution of all public methods in the class marked with Invariant
annotation:
1 2 3 4 5 6 7 8 9 10 |
|
Access to a doctrine annotations from the MethodInvocation class
Some aspects can analyze annotation to perform additional steps. Consider the following class where we define a ttl in the annotation for a method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
We can easily define a pointcut and advice that will intercept the execution of methods marked with Cacheable
annotation and cache their results in the cache for a specified time. Should be cool, isn’t it? Let’s do this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Simplified pointcut syntax for methods in the same class
Instead of complex pointcut like this:
1 2 3 4 |
|
it is possible to use or’ed constructions with |
sign:
1
|
|
Much cleaner and more readable!
Inheritance analysis during load-time
It is not a secret, that framework performs load-time weaving of aspects during loading the source file into PHP. Before PHP will be able to parse it and load, Go! AOP scans tokens and builds reflection to analyze a pointcuts. At that moment of class loading there is no information about full inheritance of class (interfaces, abstract classes, traits). This was known limitation of framework that it wasn’t possible to match parent methods in the children class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
After some research I found a way to recursively load parent classes and scan tokens. This is the major change for a dessert, but it can have an impact on the current aspects that uses within
or similar pointcuts.