Attribute Oriented Programming in PHP


The fourth talk at the Open Programming Language Miniconf 2010 was Peter Serwylo's presentation about Attribute Oriented Programming in PHP. Posted by Thomas Sutton on January 18, 2010

The fourth talk at the Open Programming Language Miniconf 2010 was Peter Serwylo’s presentation about Attribute Oriented Programming in PHP. His notes are available online.

Attributes

Attributes are “extra” bits embedded in source code that doesn’t necessarily mean anything in the language. Common examples include the documentation annotations in many comment systems (such as the tags used in Javadoc comments), JVM annotations, and .Net attributes.

A testing framework, for example, might use a TestFunction attribute to identify which methods should be called.

@TestFunction
public function testValidation() {...}
[TestFunction]
public function testValidation() {...}

Use cases

In Java EE you have “beans” which encapsulate business logic. Each bean requires a bunch of wrappers for remote access, “home” access (whatever that means), XML files, etc. Keeping all this relatively “boiler-plate” code in synch is painful. Annotating the bean classes and methods with attributes makes it possible to generate most of this automatically. No more manual synching XML files.

Java, though, (as of Java 5) has built in support for annotations and is a compiled language. This makes it relatively simple to do this analysis and generation at build time. PHP, on the other hand, doesn’t have an annotation mechanism and doesn’t have a built time.

Instead, Peter’s approach is to use PHP comments to add the attributes. At load time, these comments are processed using the reflection API and this is used to build a data structure to use for access control. See the permissions example.

A more complex case

To take this a little further, Peter wrote a Zend extension that makes it possible to [sort of] do aspect oriented programming (on function points) in PHP. The add_function_hook() function allows you to register an attribute and a callback and the extension will call your callback before a function with that attribute is executed:

<?php
class RequiresLogging
{

	/**
	 * @log notice "Secret action performed by user [user]
	 */
	public function secretAction()
	{
		// perform secret action...
	}

}

// 
// The callback function
//
function performLog( $message )
{
	$parts = split( " ", $message, 2 );
	$level = $parts[0];
	$message = $parts[1];
	Logger::log( $level, $message );
}

// 
// Register the callback
// 
add_function_hook( "log", "performLog" );

// Now code like this will result in a log message being recorded
$object = new RequiresLogging();
$object->secretAction();

This type approach is flexible and extremely powerful. You can inject permission checking code and raise an exception before the real function is even called.

There are a bunch of memory leaks and possible bugs in the Zend extension, but it is working and in production use!

This post was published on January 18, 2010 and last modified on January 26, 2024. It is tagged with: lca, events, lca2010, oplm2010, php, code, notes, aop.