Update in May 2020: I don’t think I hate PHP this much nowadays. I have barely touched it for the past 6 or 7 years but it seems to have fixed a lot of its bigger problems. Good for you PHP! Despite that, I think I’ll still stick with other languages for the time being. The trauma is just too great… :)
I hate PHP.
Even though it’s the programming language I use the most to earn my keep, I can no longer keep this inside me. For years I’ve been trying to play nice and see the good side of it but lately PHP has been making me waste countless hours, even days, to do things that should be doable in just a few minutes or a couple of hours. I just can’t take it any longer.
If my friends and colleagues don’t agree with me, I’m sorry and I hope you understand that I have nothing against you. I’d love to talk with you about this but before we do that, please read on.
Alex Munroe described it best in his great (and long) blog post, “PHP: a fractal of bad design”:
PHP is an embarrassment, a blight upon my craft. It’s so broken, but so lauded by every empowered amateur who’s yet to learn anything else, as to be maddening. It has paltry few redeeming qualities and I would prefer to forget it exists at all.
The part that bothers me the most is this: “but so lauded by every empowered amateur who’s yet to learn anything else”. This alone makes my professional life miserable, because so many people who “have yet to learn anything else” think PHP is a great thing and stubbornly defend it from everything - even if it’s not criticism, just to be safe. I should say that I have worked with very good programmers in the past who were using PHP at the time. What I’m saying applies to the majority, though, so I am generalising it.
In this post, I will point out a few higher level issues I have with PHP; things that are so basic that it boggles my mind that they haven’t been changed yet - or even worse, like the case of namespaces, that they have been implemented the way they have.
Here we go.
The ecosystem sucks
One of PHP’s most touted advantages is that it’s extremely easy to “learn” (note the double quotes). Other languages such as Python are also extremely easy to learn, so I think this is really just another fallacious argument; I think the real difference is that it’s very easy to start outputting something with Apache and PHP, whereas with Ruby or Python it takes a little more work and you actually have to know what you’re doing. And while one can easily learn how to output some HTML from Apache using PHP, that’s not the same as actually learning the language, or for that matter, learning how to develop web applications or proper software development.
This led to tons of non-programmers becoming “web designers” (note the quotes again, and hopefully you will not miss the irony), and thus contributing to the ever-expanding armies of pseudo-programmers who don’t actually know anything about algorithms, about memory management, about software engineering, about how to write maintainable code; people who spend time vertically aligning all the assignment (=) operators in a method but then write no comments on their gibberish code; people who spend hours debating whether tabs or spaces for indenting are the best choice but have no idea how to write a testable function.
The result is an ecosystem filled with crap, where one struggles to find anything - people or software - of quality.
With no real centralized system to get packages from, the problem only gets worse. Yeah, there’s Packagist and Composer (which also sucks, but I’ll get to that later), I know, but if you really want to use that as an argument, try Python’s pip or Ruby’s bundle and then let’s talk again.
Even worse, there are so many PHP “programmers”, that it’s nearly impossible to convince any of them that what they are doing is bad. There’s enough critical mass to create a sort of echo chamber that validates their bad practices. After all, if everyone else is doing it, it must be the right thing, right?
In the past few years there have been quite a few positive changes in the PHP world. Things like FIG and the PSR standards, Composer, Symfony2 and Laravel 4 are a step in the right direction but they’re still far from perfect and unfortunately, shit like Wordpress is rooted so deeply and used by so many people, that it’s impossible to do anything about it.
What this means is that if you wotk with PHP and are not part of the problem, you are basically stuck in a world of pain where you will struggle to find any decent reusable software that you can trust, or any decent developers to incorporate in your team. Sure, there are crappy programmers making use of other languages as well, but you can easily find good programmers for those, whereas in PHP the good ones are like drops in the ocean - a shark infested ocean, which makes them want to be elsewhere.
Composer should be a good thing, and in theory it is. In theory it’s a great thing, one of the best to ever happen in the PHP world. In practice, not so much.
It starts by not being able to install packages by itself. Why can’t I do something like I stand corrected. Composer can now install packages with
composer.phar install phpunit/phpunit? Why can’t I have a global installation of PHPUnit? Why do I have to create a
composer.json file even for the simplest use case, like the one I just mentioned? I can do that with Ruby and Python and no one has ever died from it.
composer.phar require vendor/package. It still has to create a
composer.json file, though…
Performance is another big issue with Composer.
As I write this, I am in the middle of a
composer.phar update execution, for a
composer.json file with 13 required packages. It has started 55 minutes ago. Yes, fifty five minutes to install 13 packages, and it hasn’t finished yet. The reason? It’s running on a spare staging server that we use for sharing the progress of our work, which “only” has 2Gb of RAM, and composer is using close to 800MB of RAM, forcing the server to swap.
Even when running with plenty of RAM, Composer is slow. Really slow. I don’t know what it does under the hood, if it clones every single repository of every required package independently of it being necessary, but it usually takes at least 5 minutes to get through a simple
composer.phar update - even when it doesn’t need to update anything! If you run it with
-vv you will see that even if you instruct it to install or update one single package, it still downloads
composer.json from every single version of every dependency!
As a concrete example, if I run
composer.phar update vendor/package in my local machine twice in a row, meaning that the second run will have absolutely nothing to update, and where
vendor/package is in a git repository in my local filesystem, Composer will take ~1m30s to run, and during that time it consumes 100% of one CPU core and ~387MB of RAM. And I used to say that Windows is bloated…
This is a stark contrast to my experience with Python’s pip, in which a
pip install -r requirements.txt execution takes just a few seconds when no updates are necessary.
With composer, it usually takes a couple of minutes before it even shows any signs of life.
Oh, and what about not downloading packages from a centralized repository, created specifically for that purpose and containing version information, and instead relying on GitHub, Bitbucket, etc, for downloading packages and listing versions? Sounds like a good idea at first, until your automated production deployments break because one of the GitHub repositories Composer tries to download from has reached its maximum downloads for the day! Yes, you can tell it to not download a packaged version and thus bypass GitHub’s API (where the limits are enforced), but if you can’t specify a version, only commit hashes or branch names, then what’s the point? Am I really expected to just trust the repo’s master branch and whatever code is in there? Or should I go and hunt down the exact commit hash for the version I want to use, so I can tell composer to fetch that instead of HEAD and make sure I suddenly don’t break a production deployment by installing a new, backwards incompatible version of a dependency? And perhaps more importantly, can I trust the developers that created the other dependencies in my project to have done the same?
It is clear to me that although a great thing in principle, Composer just cannot be taken seriously for any professional development or deployment, at least not for now.
In essence, PHP’s autoloader seems like a good idea. It saves you the trouble of having to explicitly import a bunch of files/packages/classes before you can use them.
It does so by allowing you to specify a function or method that will look for the class in the filesystem and include/require it. This means that there is no standard way to autoload a class, though, and that if you use other people’s packages, you potentially have other autoloaders at work in your code.
The best part? Since the autoloading mechanism is basically userspace code, when you have to debug your application, autoloading is not transparent and you will have to step through its code. This would be all fine and dandy if autoloaders were simple, but try using Laravel 4, take a look at the way it does autoloading, and you will see what I mean.
Ridiculous and unnecessary. Explicitly importing packages/classes never killed anyone, and making it explicit can actually save a lot of trouble. Try having two classes with similar names but in different directories, not using namespaces (there’s a lot of legacy PHP code out there), and autoload them. Which one will be found and loaded first? Fun, huh?
This ties nicely with the next point.
When it was announced that PHP was finally getting namespaces in PHP 5.3, I actually thought they were going to end the autoloading idiocy by allowing people to import classes just like any other serious language does. Turns out I was wrong.
Other languages, such as Python, Ruby and Java, allow you to import packages/classes/namespaces in a simple way. For example:
from django.conf import settings
This is Python and tells the interpreter to get the “settings” object that is available inside the “django.conf” module. As long as “django.conf” is inside one of Python’s import paths, the interpreter knows how to get it.
Same thing for Java:
This looks for a file named
Activity.java and its corresponding class inside the “android/app” directory, in Java’s import path.
In other words, the namespace/package hierarchy reflects the structure of the files in the filesystem.
Better yet, in both cases, the imported objects are immediately available via their short names (
Activity), without the need to prepend the namespace.
PHP’s maintainers didn’t think any of this was something worth implementing, so in PHP there’s still no relation between the namespaces and the filesystem, nor does it automatically load the necessary files for the required classes, meaning that we still have to resort to the autoloading stupidity of writing our own autoloader or using someone else’s.
Sure, there’s PSR-0, which defines what the PHP modules/packages' filesystem structure should be, but that doesn’t do much if the language/runtime itself doesn’t enforce it or even supports it in any way. And, you guessed it, it still requires an autoloader.
In summary, I’m sick and tired of PHP. More specifically, besides the function naming madness, the function argument order madness, the lack of decent Unicode support and the stupid problems with low-level data management, I’m sick and tired of PHP especially because of all the idiocy, amateurism and “fanboyism” surrounding it, I’m sick and tired of the time it makes me waste instead of helping me be more productive, and I’m sick and tired of having my blood boil when I hear people defend PHP as if it’s their life on the line, even though they don’t know any better - especially when they are my co-workers, because it generally means their lack of knowledge will end up causing me problems. PHP developers (not all, but quite a few) are the only developers I ever heard dismissing the use of a debugger as something unnecessary - a bunch of
echo($var)’s is not the same thing as a debugger!
I like a lot of things in PHP but I’ve reached a breaking point and I can no longer ignore the fact that the bad things outweigh the good ones, and above all, that many of the bad things have no real reason to be done that way. These bad things could be good things or at least not as bad, but they are bad because the vast majority of the people who work with PHP don’t know any better.
I’m sure with time things will get better but right now I just can’t see how someone sane, knowledgeable in software development, and with a serious job as a developer, could tolerate PHP for more than a couple of years. Unless they don’t have a choice or are not so knowledgeable in software development after all. Sorry, I know this will hit a few of my friends as well as current and past work colleagues, and I hope you don’t take it personally. It’s obviously not meant as a personal attack but you really need to look beyond PHP and try something like Python or Ruby for at least a year. I recommend you try Flask, Pyramid, Django or Rails as web frameworks. Flask is a very simple microframework, so don’t expect it to do much for you. Django and Rails are full-blown frameworks, with tons of packages available. Pyramid is somewhere in between. Whichever you choose, give it time. After you’ve done that, you will hopefully have gained enough insight and learned enough to be able to talk about this rationally and with a more informed mind.
I’ll finish with a few interesting links.
- The first one is to a Quora post where a Facebook HipHop engineer explains why he prefers Python to PHP. This is someone who works daily with PHP at Facebook, a place where they are supposed to have really great programmers at work. Most, if not all of what he says regarding Python is also true of Ruby.
- “Module Counts” is a website that simply shows how many modules are registered in each language’s central package repositories. Though not necessarily an indicator of quality, the number of packages show how popular a language is.
- Finally, although a bit outdated, “Why PHP sucks” by Darren Embry is still a good read and at the end of the article he links to other websites that talk about how problematic PHP is.
Please, do yourself - and the world - a favour and learn something else besides PHP. If nothing else, so you can make an informed decision, otherwise you will basically be making decisions blindly. How can you decide that something is the best tool for the job if you don’t know other alternatives? “Best” is a comparative term; if we have no basis for comparison, how can we know what’s “best”?