Ben Vinegar home projects archives about

ActiveSupport for PHP - Ruby style

August 13, 2007

One of the things I miss most from Rails is ActiveSupport, the module that modifies Ruby’s core classes (numbers, strings, more) with handy utility methods. They tie so well into the language, most Rails developers don’t realize they aren’t core methods.

Here’s a few examples:

>> 'hello_world'.camelize
=> 'HelloWorld'

>> 7.days.ago
=> Sun Aug 05 20:53:12 -0400 2007

>> 'purple people eater'.ends_with?('eater')
=> true

Is it possible to port this left-to-right style of coding to PHP?

Quick introduction

One of the things I miss most from Rails is ActiveSupport, the module that modifies Ruby’s core classes (numbers, strings, more) with handy utility methods. They tie so well into the language, most Rails developers don’t realize they aren’t core methods.

Here’s a few examples:

>> 'hello_world'.camelize
=> 'HelloWorld'

>> 7.days.ago
=> Sun Aug 05 20:53:12 -0400 2007

>> 'purple people eater'.ends_with?('eater')
=> true

Aside: For a near-complete list of ActiveSupport goodies, check out ErrTheBlog’s teriffic Rails Rubyisms Advent article.

The PHP way

Big chunks of ActiveSupport (mostly string inflection) have been ported to each of the major PHP frameworks, and an ActiveSupport extension has already been submitted to PEAR.

In nearly all of these cases, the functionality has been ported, but the elegance of ActiveSupport is lost in translation. Here’s the camelize example again, this time using Symfony:

sfInflector::camelize('hello_world');

As with pretty much all PHP code, it’s interpreted right-to-left instead of left-to-right, like Ruby. I prefer the latter.

The Ruby way (in PHP)

So, armed with an afternoon and a full pot of coffee, I wrote my own Ruby-like ActiveSupport library for PHP5. Here’s what it looks like:

require_once('ActiveSupport.php');

_(14)->ordinalize(); # Outputs "14th"

_(7.3)->megabytes(); # Returns number of bytes in 7.3 megabytes

_("an example sentence")->endsWith("sentence"); # Returns true

What the hell?

Okay, there’s some trickery going on here, so I’ll provide a quick explanation.

The underscore shortcut you see above is a quick way of instantiating one of four core ActiveSupport types: ActiveSupport_Integer, ActiveSupport_Numeric, ActiveSupport_String, or ActiveSupport_Array. The class you get depends on the type of the parameter you pass in. Each of these classes have been armed the same utility methods in their Rails counterpart.

What about chaining?

Ruby’s chained time/date expressions are my favourite, and they haven’t been forgotten. You can chain ActiveSupport function calls by ending them with an underscore:

_(2)->weeks_()->ago(); # Returns appropriate timestamp

_(14)->days_()->before(time()); # Same value as above, written differently

By default, all ActiveSupport function calls return primitive types (integer, float, etc) in order to play nice with traditional PHP. But when you append an underscore to the function name, you get the corresponding ActiveSupport type instead. So where _(2)->weeks() returns an integer, _(2)->weeks_() returns an object of class ActiveSupport_Numeric.

And there you have it

Want to give it a try? Download the (mostly complete) source code here (MIT License).

I’m not sure how practical this library actually is, but developing it was an interesting exercise. I was able to learn a lot about PHP’s limitations, as well as its flexibility.

As always, feedback is appreciated.

blog comments powered by Disqus
Fork me on GitHub