By Mal Curtis

Confessions of a Converted PHP Developer: Ugly Code

By Mal Curtis

I’ve been a PHP developer for nearly a decade, and in January this year I started developing in Ruby. While initially a sceptic, I’m now a convert—and I’m here to share my experiences with you. I’m far from claiming to be a gun Rails developer; I’m new to Rails, which is kind of the point of me writing this. I may not call everything by the official name, but you’ll get the gist of it.

The idea of change can often be scary. Moving to a new language from the safety of the language you know and trust shouldn’t be done lightly. I’d like to think of myself as a fairly good PHP developer, and the idea of moving to Rails was both scary and exciting. I made the plunge because of a new website we’ve developed at work and I can now confidently say I’m a convert to the Ruby way. The language and structure of Ruby is beautiful, and the speed of development that Rails provides makes my life that much easier.

It hasn’t been an easy transition. My colleagues can attest that I’ve had a fair few days swearing blinding at my laptop in frustration, usually while trying to do simple tasks. In Ruby’s defence, these are frustrations that are well made up for with the delights of finding out how easy other things are to do—and any learning process has its frustrations. It’s easy enough for me to wax lyrical about this, but let’s look at an actual example.


Ruby: Objectified

Everything in Ruby is an object. Everything. Even nothing is an object; nil is an instance of NilClass. This means that rather than the procedural “nesting,” or endless variable creation you’d have to perform in PHP, you can simply chain your method calls when dealing with any sort of variable. “Oh, that’s great, but what does that mean for ME?” I hear you ask. Well, read on.

Say that I have a string of comma-separated email addresses, and I want a list of all the unique domain names from that string. It would turn into quite a substantial process in PHP:

  // Our list of emails
  $string = ",,";
  // Explode into an array of emails
  $emails = explode(', ', $string);
  // Create a function to remove anything which isn’t the domain portion of the email
  $leave_domain = function($subject){
      return preg_replace("/^(.*)@/","", $subject);
  // Apply the function we just created to the emails array
  $domains = array_map($leave_domain, $emails);
  // Remove any repeated domains
  $unique_domains = array_unique($domains);

Which gives us:

    [0] =>
    [1] =>

So I start by exploding our string into an array; then I map a function that replaces anything except the domain part of the email, ensuring we only have unique values.

Note: I used an anonymous function for the array_map call. This would only work in PHP 5.3. You could use a foreach loop as an alternative.

That’s a fair bit of code for a simple concept. You could bring it all into one command by nesting the functions; however, this would be at the cost of readability:

  $string = ",,";
  $unique_domains = array_unique( array_map( function($subject){ return preg_replace("/^(.*)@/","", $subject); }, explode(', ', $string)));

Now that’s some damn ugly code. Try explaining that to someone without giving them a headache! The main issue here is that it has to either be nested and lose readability, or contain a veritable bunch of variables to separate out each part of the process.

In Ruby, because everything is an object, we can chain the function calls together:

string = ",,"
unique_domains = string.split(', ').map{ |e| e.gsub(/^(.*)@/,'') }.uniq

So now it’s quite obvious what’s happening. We split the string into an array, and map our replacement to each element in the array (gsub is the Ruby regular expression replacement method). Then we return only the unique values.

The beauty is that the process that occurs is the same as how you read the line. Admittedly I’m making a huge assumption here, but it reads like your normal language. Because the string variable contains an instance of the string object, we just start calling methods that belong to the string class.

This is one of the fundamental differences between Ruby and PHP, and one of the reasons why Ruby is such a great language to work with.

Will this work?

One of the biggest frustrations I’ve had while learning Ruby is my sheer lack of knowledge when it comes to knowing which functions are available, and their exact specifications or requirements. When I was learning PHP, the easiest way for me to figure this out was by coding as I wrote; that is, by trial and error. This was a relatively laborious task, and really is an efficient way to code.

Once you have Ruby installed, you get access to the wonderful Interactive Ruby Shell, or IRB for short. Anyone who’s looked into Ruby has most likely heard about it, but you may not realize how freakin’ useful it is. It’s the default place you go to answer your simple “Will this work?” questions. You can easily tap into an IRB session by typing into your console the magic three letters `irb`, and you’ll land at a command prompt. Here you can basically do anything you’d do in a normal Ruby script, one line at a time. If anything go wrong, just press “up” and fix your problem! PHP lacks anything like this out of the box, so this is a new concept to most PHP developers.

While writing the above examples, I used IRB to make sure the syntax was correct. I started a new IRB session, and set my string variable:

irb > emails = ",,"
 => ",,"

The first part there, all the way up to and including the >, is simply my IRB prompt. Next up, I’ve set the variable `emails` to a string, pressed enter, and IRB has outputted the response of the previous line; this simply tells me it’s a string.

My next action was to split the string into emails, and replace the name part of the email string:

irb > emails.split(', ').gsub(/^(.*)@/,'')
NoMethodError: undefined method `gsub' for ["", "", ""]:Array

Two things happened here. The first is that I’m using the variable I previously created, which is all good—that’s available to me for this session. Second, I ran split on the string variable, and then tried the gsub method on it.

Ruby has subsequently, and correctly, spewed out an error at me: gsub isn’t a method that you can run on an array. You need to run gsub on each of the elements in the array, rather than the array itself. Luckily, arrays do have a function that can help me: map. The map function takes a block and runs it on each of the elements in an array.

irb > unique_domains = emails.split(', ').map{ |e| e.gsub(/^(.*)@/,'')}
 => ["", "", ""]

Voilà! Using the map value, we’ve correctly created an array containing only the domains that were in the email addresses. From there it was easy enough to add the uniq method, and boom—unique domains from a string of email addresses.

By doing this through the IRB, I was able to easily see the answers to my “Will this work?” questions and debug the code until it did.

Note: Blocks are cool. They’re one of the great features of Ruby, because they’re powerful and flexible, but they’re outside the scope of what I’m talking about. I’ll tackle blocks in an upcoming blog on this site, so if you don’t know about them already, stay tuned to RubySource.

If you want to test out code specific to Rails, you can use the Rails console; this is similar, except that it loads the entire Rails environment. In your console window, make sure you’re in a Rails project directory and type `rails console` or the alias `rails c`. It’ll take a second to load, but once you’re in, you’ll have access to all your project’s models, helpers, and so forth in the Rails environment.

mal@mal:~/my/rails/project$ rails c
Loading development environment (Rails 3.0.5)
ruby-1.9.2-p180 :001 >

This is just one tip that I’ve got about starting out in Ruby when coming from PHP. I have a few more up my sleeve. Have you started in Ruby or Rails recently? If so, what tips can you share?

  • Florian

    Since I understand plain English much better than RegExpish I would prefer this:
    string.split(‘, ‘).map{|e| e.split(‘@’).last}.uniq

    Confusing, but saving some chars:

    • Mal Curtis

      Hey Florian,

      That last one does look like a better solution. There’s always more than one way to skin a cat!

      Having said that, both the PHP and Ruby solutions closely resemble each other in terms of the process – so that helps with the example.


  • Great article! I echo your accolades for Ruby (and Rails).
    As a [former] PHP guy who used Perl even before PHP existed (yeah, I am *really* old) I experienced the same frustration in making a change.
    But, once you begin swimming in the Ruby lake, it becomes apparent that the language is a sea of elegance*.

    *Trust me: I am a better developer than a poet.

  • thanks for sharing. i’ve been diving between languages but always end up where i’m most comfortable… php. i’ve tried rails 2x and i always get stuck whenever i have to create an ACL. i can never get a tutorial that helps me 100%. i find several and get left in the middle without code that works. but creating CRUDs, wow what a difference. so quick and painless.

    i’ve tried php frameworks to try to get that “rails” feeling and again i get stuck on ACL. could you share any resources you’ve found or use when dealing with authorization and authentication?

    • Steve

      You could always use a gem for authentication, “authlogic” is perhaps the best known one out there. From that it becomes quite easy to drape a bit of authorization code over the top.

      If you’re struggling with a feature in Rails, chances are someone else has as well, and they may very well have written a gem(/plugin) which will sort it all out.

    • RJ

      For authorisation stuff look on github for the following gems:


      both of which may be of interest to you.

  • benjamin

    The best piece of art are forged from who master the tools best.
    Tried Ruby alot, keep coming back to PHP. Guess both language can bring their own surprise.

    $unique_domains = array_unique($match[1]);

  • While I agree that ruby is elegant, these are the few issues i have with ruby.

    – working with dependencies is still a big headache. How can you get all gem developers to keep their gems updated?

    – PHP appears to be much more backwards compatible than Ruby. Every minor ruby version upgrade appears to be a leap jump which is incompatible with previous version.

    – I haven’t seen any complex and robust apps created in Ruby yet. unlike java and .net, I am interested to know if there are robust apps requiring good security developed in ruby.

    I think ruby is on the right track but still feel that a lot needs to be done to make it more stable and robust. I would wait for a few more years.

    • Re #1, this hasn’t been a problem for a long while – bundler/Gemfiles have solved it.

      • yes, you can bundle certain version of the gemfile together but that is not what i am saying. I am saying that there is no easy way to upgrade one version of the gemfile without doing a lot of testing and pulling hair. See how we need to specify certain version of the gem to use in the gemfile.. how do you know a will_paginate v3.1 will not break other gem? This of course will become lesser of a problem with rails become more stable.

        source ‘’
        gem ‘rails’, ‘3.0.0’
        gem ‘sqlite3-ruby’, ‘1.2.5’, :require => ‘sqlite3’
        gem ‘gravatar_image_tag’, ‘0.1.0’
        gem ‘will_paginate’, ‘3.0.pre2’

        • Let’s just assume, incorrectly, that your criticism of dependency does not apply to PHP. Even so,

          1. There are many options for specifying version dependencies in your gemfile; you don’t have to use the full version specification directly. Use the twiddle-wakka operator:
          2. Learn to use Gemfile.lock and selective bundle updates. There is a difference between Gemfile and Gemfile.lock.
          3. Upgrading a gem and verifying your application works *should* be a matter of running one command: “rake test”. Don’t complain that the tools are bad just because you aren’t using them correctly. Ruby is a dynamic language and testing is serious business, there is no compiler for confidence-generation.
          4. What unified library dependency manager do you use with PHP?

          • Stephen Cox

            This is a bit unfair since PHP doesn’t *really* need a library dependency manager.

    • euromix

      I did a big robust application in rails, it’s internal, it’s a web version of a Delphi client server application. It’s more work than Delphi, but also better for handling the environment, nothing like capistrano in client server….

  • I felt like that too… but I didn’t really switch: I use both.
    I’d use Florian solution (e.split(‘@’).last)… maybe not for performance (don’t know really), but more readable.

  • PHP does indeed have an interactive shell, so in that regard the languages are equal.

    Just start php with the flag -a from the command line.

    • php -a and irb are far from equal.

      The killers are error/exception handling (PHP generally just exits) and printing the return value of your statements (PHP doesn’t). So in terms of REPL, PHP fails at “P” and often “L”.

      Also beware that many PHP must be built with readline support to get a half-decent interactive shell. The PHP included with Mac OS X lacks this.

  • xzyfer

    @obama, I’m far from a ruby. I’ve used it a lot in the past and can’t wait to get back to PHP. But your comment “I haven’t seen any complex and robust apps created in Ruby yet.” is frankly out right ignorant. Some of the biggest SaSS applications out today are built on Ruby/Rails. The 37signal [] application suite is a perfect example. You won’t see me using Ruby/Rails any time in the near future, by choice, but it’s being used to do great things.

    As for anyone else that has doubts about Ruby/Rails being used in large scale applications, I recommend you cheap the great series of webcast at Webpulp []. It’s a tad Rails preachy, which is hands down the biggest issue with the Rails community in general, but very informative.

    • “But your comment I haven’t seen any complex and robust apps created in Ruby yet.” is frankly out right ignorant. Some of the biggest SaSS applications out today are built on Ruby/Rails.”

      An app like basecamp, twitter or digg doesn’t mean it is robust for me. Robust to me means easy to maintain, bug free and and stable. I’ll be happy to know if there is any app written in ruby and used by the banks or government. It seems java and .net are more popular in that area.

      • vladimir prieto

        @obama: “used by the banks or government. It seems java and .net are more popular in that area.”

        i’ve always thought that banks and government are one of both OR both: 1.- no innovative companies 2.- there are some kind of “agreement” between those technologies and companies, and this is not a bad thing anyway but it leaves other alternatives outside of the game.

      • salamander

        “I’ll be happy to know if there is any app written in ruby and used by the banks or government.”

        I can’t say where, but I used to work for a trading firm that used ruby extensively in a trading platform we built that was used for futures and options trading. While C++ was used for things where performance critical key, ruby was used for the less performance-intensive tasks, like back-end processing of trades.

      • Your reply is almost textbook:

        And on “robustness”, in my experience Rails applications written by experienced rubyists are some of the most well-engineered, elegant, and easy-to-maintain applications I’ve come across.

  • Is white space ignored? Similar to jQuery when you chain events you can tab them out a bit better.

    unique_domains = emails
    .split(‘, ‘)
    .map{ |e| e.gsub(/^(.*)@/,”)}

    I hope the formatting didn’t ruin this example.

    • Beau Collins

      You can put each method call on their own lines, but to make it work you need to leave the “dot” on the previous line:

      unique_domains = emails.
      split(‘, ‘).
      map{ |e| e.gsub(/^(.*)@/,”)}.

      • mkorfmann

        Well, obviously you can do both in ruby:

        1.) obj.

        2.) obj

        cheers :)

  • Great little introduction article.
    I’ve been playing with rails a while now, but had only just played with rails console and hadn’t touched irb yet!
    I have to fight with a 2.6 – 3.0.5 upgrade soon.. any chance of a article? :-)

  • You are using PHP for nearly a decade and this is how you separate domains from a list of emails? Not smart bro!

    $str =”,,“;

    will just output

    [0] =>
    [1] =>
    [2] =>

    May be yes, Ruby is really good for you! Specially if you dont know that PHP has the same capability of using PCRE :) No Offense!

    • Hey Hasin,

      I wasn’t concentrating on the best solution to the problem, I was concentrating on the differences between the same code logic in two different languages.

      You’re correct – your method is definitely a better way.

      P.S. You missed the array_unique.



  • Step 1:

    $str =”,,“;

    Step 2: Profit?

    Step 3: RTFM?

  • For the PHP version using a foreach seems like the more obvious route and makes for each steps to follow:

    $domains = array();
    foreach ( explode( ',', $string ) as $s ) {
    $domains[] = preg_replace( '/^(.*)@/', '', $s );
    $unique_domains = array_unique( $domains );

    Granted, it is still not the all OO approach that your Ruby version provides. Just saying that I think your PHP version was needlessly less attractive.

  • Hey Joseph (et al),

    I chose the example based on the fact both the PHP and Ruby solutions ending up having the same logic applied to them.

    It wasn’t designed to be the best solution in either language, it was a quick example to distinguish the difference in style.


  • is a great resource for folks trying to make the transition from PHP to Ruby/Rails. A great way to look up the functions/methods you currently use w/ PHP and instantly see the equivalent in rails!

  • aditya

    give python a try and you’ll be surprised even further, and to answer some questions raised above it is stable,easy to maintain and used in the enterprise level a lot,mobile arena ,embeded arena etc…

  • If you have more than a couple of years experience with PHP, you immediately realise how ugly it is. Elegance, however, is not the only metric by which we should measure a language’s usefulness. Accessibility should almost certainly be a factor here.

    Ruby owes it’s success to Rails, and (while not a framework) Apache is also the tail that wags PHP’s dog. If it were as easy to deploy Ruby / Python on Apache as it is PHP, then PHP’s future would less well assured.

    Looks aside, PHP arguably changed the industry for the better – encouraged hundreds of people to try their hand at coding, and superheated the small scale web development market. Many of the innovations in interface design we now take for granted often originate in a jQuery/PHP combo.
    Having said all that, I’m loving Python at the moment – much more elegant…

    • RJ

      “Ruby owes it’s success to Rails, and (while not a framework) Apache is also the tail that wags PHP’s dog. If it were as easy to deploy Ruby / Python on Apache as it is PHP, then PHP’s future would less well assured. ”

      Install Phusion Passenger – 10 minutes
      Setup capistrano for your app – up to an hour depending on your skills.

      From then on whenever you want to update your app you type “cap deploy”.

      The initial setup may not be as easy, but after that, ruby apps have a fantastic deployment system in capistrano.

  • julz

    “Cat people like ruby and dog people like python” (or is it vice versa?)

    In my humble… python too has some nice loop, text handling, and data structures that’d make your particular example a breeze.

    Here’s my simple stab at it : similiarly I’m a relatively recent convert away from php – but I chose python for various reasons. So, essentially the same: brevity, clarity, simplicity. (but less OOPy )
    string = [“”, “”, “”]
    r = set()
    for s in string:
    print r

    Nice post, btw.

  • james

    * PHP has an interactive shell (/usr/bin/php -a)
    * You can write shell scripts in PHP (and in Ruby, and in xyz)
    * PHP is a programming language, Rails is a framework. You should compare Ruby with PHP and Rails with a PHP framework
    * You can chain object methods in PHP. The functions you use are procedural so of course they aren’t going to chain. Those functions started in PHP 3 and 4 before OOP arrived in PHP.
    Just have to return $this in each method
    * If you have a string of email addresses, they’d have had to have been imploded into a string in the first place. You could cut a step and start with the source data.
    * string manipulation isn’t enough to warrant jumping from X to Y.
    * It’d be nice to see some comparisons on server load under heavy traffic running a Ruby/Rails website against some stock PHP code doing the same thing. Use Siege, benchmarking, that kind of stuff. The functions and objects used are inconsequential if the site eats memory and CPU.

    I like PHP because of the flexibility, community (lack of preachiness). In my dealings with Rails developers, they’ve all come across a tad aloof which puts you off the whole thing.

    That said, use whatever tool is best for the project.

  • There’s a chance you think that the ruby version is easier to read for the sole reason that you’re using it more often now. For all that I care both snippets of code used as an example are equally as ugly, and could be written in an equal multitude of ways regardless of language. It’s nice that you’ve found a new language that you like, but just because you began to like using Ruby doesn’t mean PHP has suddenly become ugly or inferior. You know the quote about what opinions are like :)

    • Com’on we’ve seen our share of php and sql statements mixed in with html and obtrusive javascript.

  • Beavis Smalltime

    Your article shed no light on Ruby for me. It remains a cloudy, undefined concept that so many try to explain, but few rarely do.

    99% of Ruby articles read as thus… I didn’t think I would like it, but now that I tried it, its groovy.

    I downloaded it. I found the instructions incomprehensible due to the overall hubris of the developers.

    That’s probably why it just never catches on big time.

  • I’m slowly learning the greatest that Ruby can offer. Another simple way you could also write

    emails = ",,"
    => ",,"

    unique_domains = emails.split(', ').each{ |e| e.gsub!(/^(.*)@/,'')}
    => ["", "", ""]

    using each in my opinion seems more semantic, and writing .gsub as .gsub! changes it to a destructive method. In Ruby .gsub is a search and replace method, but using that with the .each method will only return the same string. Thats because our local variable with the block |e| is temporary and disappears as soon as the block is complete. But using .gsub! changes it to a destructive method and will return our email domains to unique_domains. Its kinda like a hard copy vs soft copy deal. But I didn’t know about the .map method, would .map be more suited of handling hashes?

  • You point out in your article several instances where the simple stuff is more idiomatic in Ruby, and I agree (I came from a heavy PHP backround 4+ years ago before I was introduced to Ruby).

    But, in my experience the real gains using ruby come not from this simple stuff but from two major advantages, which are ultimately intertwined:

    1. Ability to engineer solutions with elegant abstractions. In other words – larger scale architectures that are made possible directly as a result of Ruby’s highly-dynamic features with loose syntax. Much of this is embodied in Rails and good Rails apps are almost poetic in the way they use ruby to craft web applications.
    2. Presence of self-contained libraries for almost everything imaginable. Many of these libraries can only even be conceived in the context of the dynamic features Ruby providers. Look at a gem like meta_where and the scale of Ruby’s dynamic nature truly comes out.

    That being said, like any powerful tool, ruby is invariably more difficult and more error-prone to use by many newer developers (either folks new to the language, or those general adverse to well-engineered code).

    Still though, I always say that variance in language features/capabilities is still fair less than variance in *developer* productivity. I’d take a great developer working with PHP over a bad developer working with Ruby any day of the week.

  • R

    I see your point, but I don’t SEE YOUR POINT?

    Your example, yes in Ruby and PHP can be written completely in a one line of nested dot class notation jimble jamble code or function in a function mangled jumble of code.

    However, after 13 years in the web development business I have never came across a problem where I needed to make a unique list of domain names from a comma separated list of emails in a string. Maybe someone can tell me why I absolutely need to have this?

    If I did have this problem to solve I would prefer that the person working for me or myself would write it line by line in an easy to understand and follow way. Then wrap it all up in a class method or function. All be it some of the RegEx gurus out there already commented on how to do it as well with less. Love RegEx!

    If I was designing the perfect web development language from scratch “dot” class notation nested would be nice but not necessarily the most important thing.

  • Your coding examples seem to be messed up, I see just

  • Interesting, it looks just dandy on the comment view page!

  • PHP is not having all the features that Ruby offers, but it is good enough to get the job done at hand.

    There are some great pieces of software written in php and they are used widely. Let us take an example – wordpress. The very comment I am writing right now will be consumed by a wordpress installation on which is hosted. A person with few months of experience on programming in web can easily look and modify the php source code to suite thier need. If that guy has to go the rails route then he has to at least learn Ruby and Rails for a few months.

    Remeber when php was into practice, agile development methodologies were not practiced and discussed like in the Rails domain.

    PHP would be still a choice of language when it comes to quickly ramp up something and get the product to market, in order to gain confidence of board by “any average programmer”.

Get the latest in Ruby, once a week, for free.