Practical uses for reflection

February 16, 2009 – 4:30 pm Tags: ,

You may have heard about the reflection feature in PHP. Simply put, it’s a way to get a list of methods in a class, a methods parameters, or other “internal” things like that. But how is this actually useful for any common task in application development?

A usage scenario

Most web applications use forms. Forms often represent some model, such as a newspost. If the model is simple, writing the form in HTML is not too bad, or we might be able to use a scaffolding feature in our framework.

But what if the model has lots of data in it, and we are just writing some small application, which doesn’t necessarily require a big framework with features for form generation?

Here’s a good use for reflection! Since in models we often have a naming scheme for the data the users would be able to input, we can utilize this knowledge with reflection to generate a list of possible fields in the model, and then generate the form with less typing required from us.

Example implementation

Let’s use the newspost as an example. Typically, you would have things such as title, description, who wrote it, publication time, and maybe some additional fields like edit time, and whether or not comments are enabled.


example model

The model for this would usually contain methods like setTitle, getTitle etc. for setting and gettings each value. It might also have some additional methods, but we won’t need to think of them now.

By using reflection, we can get the list of methods in the model. Since we also know that each of available fields will have a getter, we can loop through the methods and just get every method which starts with get:

$cls = new ReflectionClass('NewsPost');
$methods = $cls->getMethods();
 
$fields = array();
foreach($methods as $method) {
  if(substr($method->getName(), 0, 3) == 'get') {
    //Just take everything after get as the field name
    $fields[] = substr($method->getName(), 3);
  }
}

Now the fields array will hold each field in our class, and we can use that to generate a form without writing lots of HTML:

<?php foreach($fields as $field): ?>
  <p>
    <label for="<?php echo $field; ?>"><?php echo $field; ?></label>
    <input type="text" name="<?php echo $field; ?>" id="<?php echo $field; ?>" />
  </p>
<?php endforeach; ?>

Depending on your model class, you may wish to perform additional formatting of the field names, so using it as the label will make more sense, such as replacing “CamelCase” with “Camel case”:

$labels = array();
foreach($fields as $field) {
  //Using temp variable for the sake of readability
  $label = preg_replace('/([a-z])([A-Z])/', '$1 $2', $field);
  $label = ucfirst(strtolower($label));
  $labels[] = $label;
}

Further improving the form generation

As mentioned earlier, the news post could have a boolean value for whether or not comments are enabled. This can’t really be represented by a text input box.

What if there was a way to know the value returned by the getter? In that case we could just show a checkbox… but oh wait, there is a way!

/**
 * Are comments enabled?
 * @return bool
 */
public function getCommentsEnabled()

Another reason to write docblocks for your methods – We can use reflection to read the docblock, and read any annotations such as the @return value.

We’ll modify our earlier example of getting the fields to include a field type:

$cls = new ReflectionClass('NewsPost');
$methods = $cls->getMethods();
 
$fields = array();
foreach($methods as $method) {
  if(substr($method->getName(), 0, 3) == 'get') {
    //the field is a textbox by default
    $field = array(
      'name' => substr($method->getName(), 3),
      'type' => 'text'
    );
 
    //we want bools to show up as checkboxes
    if(strpos($method->getDocComment(), '@return bool') !== false) {
      $field['type'] = 'checkbox';
    }
 
    $fields[] = $field;
  }
}

We can use the method getDocComment() to access the docblock of a method. We can then use strpos to check if @return bool exists in the docblock.

Conclusion

Reflection, a feature which may seem a bit useless for everyday tasks, can actually be very useful with a little ingenuity. We could extend the examples shown in the post to even include code for parsing the input from the form after its submission, but I will leave that as an excercise to you.

Have you used reflection to do something interesting? Please post your ideas/applications to comments!

Share this:

RSS feed Subscribe to my RSS feed

About the author

Jani is a 15 year veteran of the software industry. He's currently available for consulting

  1. 15 Responses to “Practical uses for reflection”

  2. nice example of reflection usage.

    I saw a nice example where you could use the reflection API to do multiple extends of classes witch i found usefull in one of my projects.

    By solomongaby on Feb 16, 2009

  3. How about performances of the PHP Reflection API ?

    By The Sorrow on Feb 17, 2009

  4. Another great use: Documenting PHP extensions/classes/functions:

    http://cvs.php.net/viewvc.cgi/phpdoc/scripts/docgen/

    This generates DocBook based skeletons that are later revised with content and added to the official PHP Manual.

    By philip olson on Feb 17, 2009

  5. You can also use Reflection to get undocumented information about a class; like functions, methods, constants, etc…

    http://bdewong.blogspot.com/2008/03/blog-updates.html

    By Brent on Feb 21, 2009

  6. Looks like that’s useful for undocumented (or not-so-well documented) Classes. I think that will be more of a debugging/learning tool ;)

    By Filipe La Ruina on Feb 27, 2009

  7. Excellent examples. I didn’t know this was possible until now.

    By pfwd on Oct 14, 2009

  8. This is really nice example for reflection beginner. Thanks a lot for providing this example. Its easy to understand.

    By Hardik on Apr 27, 2010

  9. poo

    By bob on Aug 5, 2010

  10. Now i got some ideas about the use of reflections.
    Thanks

    By Sunsocheth SORN on May 25, 2011

  11. I think you should make a list of uses for reflection

    By Amy Pip on Sep 25, 2011

  1. 5 Trackback(s)

  2. Feb 18, 2009: Zend_Acl part 3: creating and storing dynamic ACLs | CodeUtopia
  3. Feb 20, 2009: Closures coming in PHP 5.3 and that’s a Good Thing | CodeUtopia
  4. Feb 26, 2009: Using models as criteria objects for querying the database | CodeUtopia
  5. Feb 4, 2011: Algunos links interesantes « unreal4u's Personal Network
  6. Jul 7, 2011: Zend_Acl часть 3: создание и хранение динамических ACL | Zend Framework – интересные для меня моменты

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)