Aspect Oriented PHP
7
A proof of concept idea I had for implementing an aspect oriented framework in PHP (yes, I know about http://aophp.net, but it requires a module).
I thought it was neat, so I'm going to share it.
Hope someone likes it.
I thought it was neat, so I'm going to share it.
Hope someone likes it.
<?php
/**
* The core AOP class
*/
class AOP {
private $_inner;
private $_before = array();
private $_after = array();
public function __construct($inner) {
$this->_inner = $inner;
}
public function inject_before_call($pattern, $method_name) {
$this->_before[] = array("/".$pattern."/", $method_name);
}
public function inject_after_call($pattern, $method_name) {
$this->_after[] = array("/".$pattern."/", $method_name);
}
private function __call($method_name, $params) {
foreach ($this->_before as $lookup) {
list($pattern, $before_method_name) = $lookup;
if (preg_match($pattern, $method_name)) {
call_user_method_array($before_method_name, $this, array($method_name, $params));
}
}
$result = call_user_method_array($method_name, $this->_inner, $params);
foreach ($this->_after as $lookup) {
list($pattern, $after_method_name) = $lookup;
if (preg_match($pattern, $method_name)) {
call_user_method_array($after_method_name, $this, array($method_name, $params, $result));
}
}
return $result;
}
}
/**
* Provides logging at the beginning of a method invocation, and when the method
* returns
*/
class LogAdvice extends AOP {
public function __construct($obj) {
AOP::__construct($obj);
$this->inject_before_call(".*", "log_start");
$this->inject_after_call(".*", "log_end");
}
public function log_start($method_name, $params) {
echo "START: {$method_name}\n";
}
public function log_end($method_name, $params, $result) {
echo "END: {$method_name}\n";
}
}
class TimingAdvice extends AOP {
private $_clock_times = array(); // Stack used for clock ticks
public function __construct($obj) {
AOP::__construct($obj);
$this->inject_before_call(".*", "begin_timing");
$this->inject_after_call(".*", "end_timing");
}
public function begin_timing($method_name, $params) {
array_push($this->_clock_times, microtime());
}
public function end_timing($method_name, $params, $result) {
$start_time = array_pop($this->_clock_times);
$end_time = microtime();
$duration = round(($end_time - $start_time)*1000, 5);
echo "{$method_name} took {$duration}ms\n";
}
}
class TestObj {
public function test1() {
echo "Test1 Called\n";
}
public function test2() {
echo "Test2 Called\n";
}
}
// The gluing together of objects would be done by the container (as in the Spring Framework)
// So even though the next line is ugly, you'll note that the TestObj class above remains simple.
$test = new TimingAdvice(new LogAdvice(new TestObj()));
$test->test1();
$test->test2();
?>






Fairline32