Introduction
In the past, I've come down hard on ASP.NET for trying to be an all-in-one solution. Rather, I've come down hard on ASP.NET developers trying to make it into an all-in-one solution. ASP.NET is an unsurpassed language for enterprise development and other medium-to-large scale projects. Despite significant improvements in 2.0, the simpler your project gets the more you begin to notice .NET's overhead (no, I'm not talking about performance). In fact, everything that makes ASP.NET a great toolset for large-scale development is what makes it such a bad choice for anything small.
On the flip side, PHP excels at this type of small/medium work. It's extremely easy and quick to put something together and supports an incredible amount of kludging before falling apart. Of course, everything that makes PHP such a great toolset for small-scale development is also what makes it such a horrid choice for any large-scale projects or any sized enterprise development.
I just want to take a little sidetrack to acknowledge that there are in fact tons of large and complex PHP websites out there as well as tons of small ASP.NET sites. In the end, despite everything I'm going to say, the individual developer has far more impact on a project's success and implementation than the tool he or she uses.
PHP is NOT Object Oriented
As a language, PHP's object-support is quite rich. Since the introduction of PHP5, developers have had the same level of OO support as most other languages. Of course, there's nothing forcing developers to use OO principals. This is a mixed blessing. For projects with a small domain, I've found that OO can slow down development without brining any substantial benefits. For projects with a medium/large domain, developers are left on their own to do the right thing. I've heard it said more than once, but PHP doesn't have a culture of objects. The PHP community hasn't bought into the concept of OO the way the Java, Rails and .NET communities have. Whether that's an issue with PHP or an issue with PHP developers is hard to say. VB6 had decent OO support; most VB6 developers just didn't buy it (or maybe they didn't grok it).
As a framework, PHP fails to leverage OO in any meaningful way. The fact that PHP itself isn't OO explains why developers don't use PHP's OO features. In .NET everything's an object. Want a textbox? Declaratively create a new textbox objects, programmatically set properties and execute member functions. Most PHP, VB6 or classic ASP programmers just don't get it. Think of it this way, in .NET you create a server-side DOM, manipulate it with a very rich API and an event model then render it out. This is particular useful when you want to extend the built-in objects and achieve greater re-use (within the same project or with completely separate projects). There are countless other examples, such as user controls, HttpModules, HttpHandlers and the page lifecycle which are completely foreign concepts to PHP developers.
Beyond the presentation layer, PHP's vast library is also mostly procedural. The contrast between the MySQL and MySQLi libraries is a good example of how PHP is (MySQL) and how it should be (MySQLi). However, almost all of PHP's libraries are procedural: string manipulation, regular expressions, sessions, ftp, sockets, Images, database access (MySQLi is the exception) and so on.
With PHP's own miserable ue of OO, it's not hard to understand why PHP developers don't leverage OO as much as they could. OO is hard, and PHP neither demands it nor does it bother promoting it.
Layering
The only support for layering offered by PHP is the include/require functions. Like OO, proper layering can greatly increase code readability and maintainability. Much like in classic ASP, most developers tightly intertwine their PHP and HTML. The resulting code is truly worthy of being labeled spaghetti for its incomprehensibility and the difficulty to maintain. "echo" is core to PHP development, while the equivalent Response.Write is scarcely found in ASP.NET. Despite being easily abused, ASP.NET's CodeBehind model and DataBound controls are well ahead of any PHP offering. The lack of OO buy-in often leads to anemic domains. On the data access front, the .NET community is as far ahead of PHP as Java is ahead of .NET. The introduction of LINQ in the next version of .NET will put it squarely ahead of all if developers adopt it.
The first example of the MySQLi documentation in the PHP manual highlights the problem perfectly:
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";
if ($result = $mysqli->query($query)) {
/* fetch associative array */
while ($row = $result->fetch_assoc()) {
printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);
}
/* free result set */
$result->close();
}
/* close connection */
$mysqli->close();
?>
I can't really think of a worse way to write this. True, this is only a reference document, but most PHP code follows the same pattern.
Exception Handling
Exception handling in PHP is like object oriented programming – it's supported but not used. The PHP framework scarcely makes use of structured exception handling as do most of the online samples. The example which always gets under my skin is the MySQL library. Check the return value to see if a connection failed and echo out mysql_error() . Anyone who thinks using "or die" is any better just doesn't get it. Even the much improved MySQLi library didn't get it right.
It doesn't really get any simpler than this: a failed database connection should throw an exception and in almost every case developers should let it bubble up to the global handler. I'm sure they exist, but I couldn't find a single standard PHP library which actually uses exceptions.
There's a base exception class which you can extend, great! But why bother when you'll still have to do that oh-so-dated return value check all the time. PHP developers are quick to point out that PHP 5 has first class exception handling but slow to actually use it.
Other Issues
The fact that PHP is a loosely typed language can lead to significant difficulties for larger projects. Strongly-typed languages like C#, VB.NET and Java can take full advantages of compile-time checking and design-time tools (IDEs) while loosely-typed ones generally can't. (I have little experience with PHP IDEs, so maybe this isn't as much of a problem as I think it is). Like everything else we've covered, the lack of strong typing generally makes PHP ideal for smaller projects and problematic for larger ones.
.NET also has a clear edge when it comes to tool support. Visual Studio has long been considered one of the best IDEs around. It does cost a fair chunk of change (we are talking about medium/large apps though), but there's the free Express line which is quite adequate. For very large projects, PHP doesn't have anything like Team System. When it comes to profiling, debugging and refactoring ASP.NET is ahead by at least a couple years. VS.NET's projects, solutions and references are all integral to code re-use. PHP largely goes by the copy-n-paste approach.
Although both PHP and .NET lag behind Java when it comes to Agile methodologies, there's considerably more awareness and support for Test Driven Development, unit testing and Continuous Integration within the .NET community. .NET's tools are more mature and widely used. Searching for information on TDD, unit testing and CI for PHP returns only a handful of useful/relevant hits.
Conclusion
VB6 and VBA share a lot more in common with PHP than with either VB.NET or C#. More pointedly, VB6 developers share a lot in common with PHP developers. Despite having some of the necessary tools, PHP developers (including those working on the actual PHP codebase itself) seem unwilling or unable to make use of core software engineering methodologies.
From my own experience, and the countless of online tutorials and blogs, many PHP developers are guilty of the same crap code VB developers were once renowned for. OO, N-Tier, exception handling, domain modeling, refactoring and unit testing are all foreign concepts in the PHP world.
This isn't an anti-PHP rant – it's a using the right tool for the job rant. There are frameworks out there for PHP which help solve a lot of the inherent issues, but like ASP.NET some of the limitations are built-in (you can't get around C#'s strong-typing and you can't get around PHP's loose-typing). There are MVC frameworks, O/R mapping frameworks and Agile tools. Despite those, with the 5 year anniversary of ASP.NET a couple months away, and significant innovation in the next release of .NET, PHP is starting to lag far behind.
