Fair warning: If you have never used PHP, and had to click on that Wikipedia link up there, you can probably go ahead and skip this post entirely.
- Data structures: PHP has one data structure, which PHP coders refer to as an "array". I refuse to call it that, for the simple reason that it's actually not an array, or indeed any kind of named data structure. What PHP calls an array is actually closer to a hash table, only not really because it also has ordered keys, so that it can act like either an array or a hash table. The question occasionally comes up: If I want to use a PHP array as an array, what do I do when it's actually a hash table, or vice versa? The answer, if you're a PHP dev, is: Pretty much whatever the hell you want. Consistency? Who needs it!
- Security: It is pretty easy, all things considered, to write secure PHP code. The problem, unfortunately, is that it's much much easier to write insecure code. Generally, programmers get the blame, and rightly so, but the language deserves at least some of it. There are some PHP "features" that are such obvious security clusterfucks that it's a wonder they ever made it in in the first place. Two of the more glaring ones are remote includes, where you can pull a file off the internet and execute it, and register_globals, which allows the remote user to put whatever the hell variables they want in your global scope.
- Configuration files: When core language behavior is controlled by a configuration file, it really makes it hard to write code that will work everywhere. The most egregious example I can think of is magic quotes, which when enabled will break scripts that don't expect it, and vice versa. (Magic quotes are stupid for several other reasons; I'll get to that later.) When you make core language features configurable, it saves you some pain in the short run, but in the end you have to handle both cases properly in your scripts. More proof that it's a bad idea: name one other language, any one is fine, that has core language behavior made optional by a configuration file.
- Poor feature support: What do namespaces, threads, compiled modules, arrays, Unicode support, and comprehensive standard libraries all have in common? None of them can be found in PHP. (Actually, Unicode is supported through a few different competing PHP extensions, none of which are guaranteed to be enabled. If you're willing to count that as Unicode support, you might be beyond help.)
- The whole "whatever works" attitude: Frankly, this attitude is pervasive when it comes to PHP, but my personal favorite example is magic quotes. One day, somebody realized that a lot of PHP scripts were vulnerable to SQL injections. There are a lot of solutions to this problem, but the path PHP eventually chose was to preescape all the strings coming into a script, just in case they would end up in a database query. This fixes most of the poorly written scripts out there, at the expense of breaking all the scripts that were correct in the first place. Normally, you'd prioritize working code over broken code, right? That is why you're not a PHP developer. They saw something that would work most of the time, and they grabbed for it, and we're still paying for it today in all the extra backslashes you occasionally see on the web.
Overall, my problem with PHP is that the language was never really designed; it started as a glorified template processor and just kind of aggregated from there. Nobody ever actually steps back and looks at the design of the language, and it really shows, in a ton of little ways.