Attributes, reflection and PHP

After a long exposure to .NET, when I get back to PHP I sometimes find myself missing some cool functionality (and a good IDE too… none of those I’ve tried so far can compete with the comfort of VisualStudio + ReSharper).

Among these missing features, attributes are what I needed in order to solve a certain problem in an elegant way.

Looking at what the reflection API was offering, I came up with a simple way to decorate my properties/methods/classes with attributes: through the documentation comments!

Let’s see an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<pre>
<?

class A
{
    /**
     * @attr
     * @attr2      
     */

    protected $foo;
   
    protected function GetPropAttrs( $property )
    {
        $class   = new ReflectionClass( get_class( $this ));
        $prop    = $class->getProperty( $property );
        $doc     = $prop->getDocComment();
        $attrs   = array();
        $matches = array();
                   
        preg_match_all( '/@([a-zA-Z_][a-zA-Z_0-9]*)/m',
                                $doc, $matches, PREG_SET_ORDER );
       
        foreach( $matches as $m )
            $attrs[] = $m[ 1 ];

        return( $attrs );
    }
   
    public function test()
    {
        $attrs = $this->GetPropAttrs( 'foo' );
       
        print_r( $attrs );
    }
}

class B
extends A
{
    /**
     * @attr3      
     */

    protected $foo;
}

$obj = new A();

print( 'Test A:<br>' );
$obj->test();

$obj = new B();

print( '<p>Test B:<br>' );
$obj->test();

?>
</pre>

Running the above script you’ll see the following output, confirming that everything works as desired:

Test A:
Array
(
    [0] => attr
    [1] => attr2
)

Test B:
Array ( [0] => attr3 ) 

If you’re using the /** */ comments for real documentation, you might want to use another escape character rather than @, to avoid problems.

Happy coding 🙂

2 comments

Leave a Reply

Your email address will not be published. Required fields are marked *