8. Aspects of Love
namespace AppHttpControllers;
use AppUser;
use AppHttpControllersController;
class UserController extends Controller
{
public function showProfile($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
Route::get('user/{id}', 'UserController@showProfile');
9. Aspects of Love
But only Logged-
in Users should
be able to see
another User’s
Profile
10. Aspects of Love
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
...
}
Route::get('profile', 'UserController@showProfile')
->middleware('auth');
11. Aspects of Love
We need to log
every time that
somebody views
any User’s
Profile
12. Aspects of Love
Don’t forget that
we also want to
cache recently
accessed User
Profiles to improve
performance
13. Aspects of Love
And in the
functionality to
Edit a User’s
Profile, we need
an audit record
of all the changes
that were made
Except
passwords
(of course)
14. Aspects of Love
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('log');
$this->middleware('audit')->only('edit');
$this->middleware('cache');
}
...
}
22. Aspects of Love
Terminology
Aspects apply Advices at “Join
Points”
Points within the Business
Logic
where the additional
behaviour
should be joined
23. Aspects of Love
Terminology
Join Points are identified by
“Pointcuts”
Expressions that identify one
or more
Join Points where an Advice
should be applied.
26. Aspects of Love
namespace SystemAspect;
use GoAopAspect;
use GoAopInterceptMethodInvocation;
use GoLangAnnotationBefore;
class LoggingAspect implements Aspect
{
/**
* @Before("execution(public *UserController->showProfile(*))", order=-128)
*/
public function beforeMethodExecution(MethodInvocation $invocation)
{
Log::info(sprintf(
'Access to %s with arguments %s’,
$invocation,
json_encode($invocation->getArguments())
);
}
}
27. Aspects of Love
namespace SystemAspect;
use GoAopAspect;
use GoAopInterceptMethodInvocation;
use GoLangAnnotationBefore;
class LoggingAspect implements Aspect
{
/**
* @Before("execution(public *UserController->showProfile(*))", order=-128)
*/
public function beforeMethodExecution(MethodInvocation $invocation)
{
Log::info(sprintf(
'Access to %s with arguments %s’,
$invocation,
json_encode($invocation->getArguments())
);
}
}
28. Aspects of Love
namespace SystemAspect;
use GoAopAspect;
use GoAopInterceptMethodInvocation;
use GoLangAnnotationBefore;
class LoggingAspect implements Aspect
{
/**
* @Before("execution(public *UserController->showProfile(*))", order=-128)
*/
public function beforeMethodExecution(MethodInvocation $invocation)
{
Log::info(sprintf(
'Access to %s with arguments %s’,
$invocation,
json_encode($invocation->getArguments())
);
}
}
36. Aspects of Love
And that’s the Magic!
AOP allows us to do “stuff” before or
after a method call (or even override
it completely),
without modifying the original code!
38. Aspects of Love
But the number of AOP
Libraries/frameworks that are
available suggests that some people
do like their magic
39. Aspects of Love
AOP Libraries/Extensions
AOP PECL Extension
PHP 5 (there is a PR for PHP 7, but
unmerged)
https://github.com/AOP-PHP/AOP
http://aop-php.github.io/
40. Aspects of Love
AOP Libraries/Extensions
JMS AOP Bundle
For Symfony 2+
http://jmsyst.com/bundles/JMSAopBundle
https://github.com/schmittjoh/JMSAopBu
ndle
41. Aspects of Love
AOP Libraries/Extensions
Lithium Framework
https://github.com/UnionOfRAD/lithium
42. Aspects of Love
AOP Libraries/Extensions
Ray.Aop
https://github.com/ray-di/Ray.Aop
43. Aspects of Love
AOP Libraries/Extensions
Kdyby/Aop
For the Nette Framework
https://github.com/Kdyby/Aop
44. Aspects of Love
AOP Libraries/Extensions
Swoft
Coroutine componentisation Framework,
based on swoole 2 native Coroutines
https://github.com/swoft-cloud/swoft
45. Aspects of Love
AOP Libraries/Extensions
Flow
Formerly Typo3 Flow, formerly Flow3
https://flow.neos.io/
46. Aspects of Love
AOP Libraries/Extensions
Go! AOP
https://github.com/goaop/framework
https://go-aop-php.readthedocs.io/
47. Aspects of Love
Go! AOP framework
Symfony Bundle:
https://github.com/goaop/goaop-symfony-bundle
Laravel bridge:
https://github.com/goaop/goaop-laravel-bridge
Zend 2 module:
https://github.com/goaop/goaop-zf2-module
IDEA plugin (PHPStorm, IntelliJ):
https://github.com/goaop/idea-plugin
50. Aspects of Love
Clarke’s third law
“Any sufficiently advanced technology is
indistinguishable from magic.”
Arthur C. Clarke, “Profiles of The Future”, 1961
51. Aspects of Love
Go! AOP – How does the magic work?
Wraps the Composer loader with its own proxy
Intercepts calls to load a class file, and
applies its own stream filter to read the file
without actually “loading” it
Tokenises and parses the file to an AST (using
the nikic/PHP-Parser library), and applies
static reflection
52. Aspects of Love
Go! AOP – How does the magic work?
Checks all registered pointcuts and transforms
the original class code, renaming it as
<class>_AopProxied
Creates its own version of the original class
file, with the additional logic from the
relevant Advices, extending <class>_AopProxied,
and stores that new file in the cache folder
53. Aspects of Love
Go! AOP – How does the magic work?
Directs the autoloader to load the new file from
the cache folder
Autoloader will subsequently load
<class>_AopProxied as well, because the new
version of the class extends that, but no
further transformation is required
60. Aspects of Love
Potential Benefits with AOP
Separation of Concerns
Separate Unit Tests for Business Logic
and for Aspects
Simplifies Unit Testing for Business
Logic
No need to mock Aspect Objects
like Loggers
62. Aspects of Love
Libraries Using AOP
AspectMock
https://github.com/Codeception/AspectMock
Roave/StrictPHP
https://github.com/Roave/StrictPhp
PHPDeal (Design by Contract)
https://github.com/php-deal/framework
64. Aspects of Love
The Future?
Composite Oriented Programming
https://www.infoq.com/articles/Composite-Programming-
Qi4j
Aspect Oriented Programming
Dependency Injection
Domain-Driven Design
65. Aspects of Love
The Future?
Apache Polygene
https://polygene.apache.org/
Behavior Depends on Context
Decoupling is a Virtue
Business Rules (and Domain Model) matters
more
Classes are Dead, Long Live Interfaces