These are both web-application frameworks that serious J2EE-type developers tend to sniff at, claiming that they may be fine for simple toys but are not suitable for real projects. Otherwise, however, the two are drastically different: PHP encourages a page-oriented architecture and makes you do a lot of extra work to get any kind of model-view-controller (MVC) setup; Rails enforces an MVC architecture with pre-defined naming conventions for database tables, etc., and makes you do a lot of extra work to design your application any other way.
I’ve long been an MVC and Java servlet fan. I love object-oriented programming, use REST as a web architectural style, and tend to think of XML-encoded data in entity-relationship terms. So why did I like PHP so much better than Rails?
I think that the answer has to do with the fact that web applications — whether producing HTML for people or XML for machines — are really about views, not objects. In anything but the most trivial cases, the views involve information from many different types of objects merged together to create a new object type. The most common way to generate these views is through SQL queries joining together different tables, and the columns in the result set define the properties of the new object type. I’ve spent a lot of time trying to use and trying to write object persistence layers for web applications, but they never made sense — my models always progressed quickly through the simple CRUD steps (X.create, X.read, X.update, X.delete) but then fell apart as soon as I tried to make my app do anything other than manage its base data. Should I define a new Java class for every possible kind of query result? How do I handle results that do not involve full objects? If I’m not getting full objects in query results, what’s the point of a persistence layer in the first place?
After all that soul-searching, prototyping an app in PHP was like a cool breeze on a hot day. I wrote a few helper functions to automate escaping values to avoid SQL or HTML insertion attacks, but I managed to fight off the temptation to write a persistence layer in PHP. Instead, each page has some PHP code at the top that makes one or more SQL queries, followed by HTML markup with only minimal PHP added to insert dynamic results. It works, it actually seems scalable and maintainable, it’s easy to deploy (just about all ISPs already support PHP, so you just upload the *.php files), and debugging is trivial, because the query is right there on the page with the HTML that will display its results. Bugs are not buried deep beneath 20 layers of abstraction, and the database and filesystem are the only shared state.
Rails, on the other hand, was a disappointment. It tries to make my database invisible so that I think I’m dealing only with objects, but my database, and its query capabilities, are what will make my application more than just a collection of objects with a simple search box. I ran into a bug during one of the tutorials and it was almost impossible to trace the problem due to the deep layering. And the only thing that Rails seems to simplify is the basic CRUD operations, which are the easiest part of any web app. Rails also tries to tell me exactly how to set up my database and page hierarchy — I know that I can change it, but by the time I’ve learned to do that, would Rails still be any easier?
I don’t know if I’m ready to jump to PHP for serious development yet. Java has a lot of good libraries for XML and supports Unicode well, and J2EE also lets me develop in a page-oriented model if that’s what I really want (though I have to do a lot of configuration rather than simply plopping a file into a directory). At the very least, though, I’m going to stop worrying about abstracting away the database and will try to learn to love it, whatever environment I use.