Rob's Tips and Tricks

I have been working on a back-end management UI for a client of mine, and ran into an old, old problem in web development - plural nouns. I found my code filled with lots of conditional code to determine when to add an "s" to things, eg: "You have 1 active listing" vs "You have 2 active listings"

In Rails, I have a pluralize method to help (though it only goes so far), and I was looking for something similar in PHP, which led me to this excellent post over at kuwamoto.org.

It was the perfect thing - a port of Rails' pluralize/singularize methods in PHP, with a few improvements to boot.

Once I had the code installed on our system, however, I found that it wasn't enough. I still had conditionals. I still had blocks of ugly code to make things work. So I came up with something better...

The Clever Bit


I wrote the following function to take not a single word, but a phrase. It pulls out the last word in the phrase, and pluralizes it. The clever bit is, if there's a number in the phrase, it conditionally pluralizes the last word. This was exactly what I needed in my code, and allows me to concisely and elegantly solve one of those niggling problems all web developers deal with.

Check out the function here:

The function
/**
 * Takes a string or phrase, and pluralizes the
 * last word in the phrase.  If there's a number in the phrase,
 * conditionally pluralizes the last word based on the number.
 */
function smart_pluralize($str) {
  // Extract
  $regex ='/[^0-9]*([0-9,]+)?.*(?:[^a-zA-Z]|^)([a-zA-Z]+)[^a-zA-Z]*$/';
  preg_match($regex, $str, $res);
  list($amt, $word) = array_shift($res);
  if ($word) {
    if (strlen($amt)) {
      $word = Inflector::pluralize_if($amt, $word);
    } else {
      $word = Inflector::pluralize($word);
    }
    $str = preg_replace('/([^a-zA-Z]|^)([a-zA-Z]+)([^a-zA-Z]*)$/', "$1$word$3", $str);
  }
  return $str;
}

Examples


Here are some sample strings, and the result of running them through smart_pluralize():

  • "bunny" => "bunnies"
  • "1 dog" => "1 dog"
  • "5 dog" => "5 dogs"
  • "25 happy person!!!" => "25 happy people!!!"

Integrating it with Smarty


Now that I had a smart phrase pluralizer, I needed to integrate it into Smarty, my template system of, er, choice. :-)

I wrote a Smarty block helper named "pluralize" that simply passed the contained text into smart_pluralize() and voila! Clean templates:

Smarty integration
Welcome to WidgetCorp.com.  You have {pluralize}{$count} widget
item{/pluralize} in your shopping cart.

Just write your text in singular, include the count in the phrase somewhere, and you're off and running.

It's been a real blessing, hope you find it helpful as well!

About

Web home of Rob Morris, software guru and all-around great guy. A place to post and discuss code and the software development lifestyle.

Archive

July 2010 (1)September 2009 (1)August 2009 (2)