Why I dislike PHP

by Lukas Prokop, 2011.07

In Dec 2006, I have learned PHP to help some cool guys of my secondary school. They maintained a phpbb board to provide students a communication platform for all forms and people. The project was ended in Dec 2008 and I was introduced to programming by learning PHP. Actually, in summer 2008 I wrote my first Python program and started to learn its basics in 2009. In this situation, I was left with my webdevelopment experiences up to now, studying computer science and learning other programming languages. Even though my love to python is evolving, my primary language has been PHP. However, I want to leave a comment, why I now decided to end my old PHP projects and stop developing with this programming language.

At the time of writing this article, PHP 5.3.8 is the stable release.

Mixed paradigms

I think my major problem with PHP is the mixing of different paradigms in the language. PHP provides you tools for imperative, procedural, structured, functional and object-oriented programming. But PHP does not provide any possibility to use those paradigms consistently and on an intuitive level. By the way, concurrency, DSLs or declarative programming approaches are not possible or easy to implement in PHP. IMHO, PHP does not provide the freedom to the developer he deserves. Also every feature in PHP was introduced by other languages before. I don't think PHP is interesting from a compiler design or software paradigm point of view. Type juggling is the only concept I can think of and it's a design flaw in my opinion.

The set of string, integer, float, boolean, NULL and array data types is the most basic data type collection every general-purpose programming language has nowadays; focusing third-generation programming languages (ie. Java, C++, C#). PHP provides all of those and adds some special magic to arrays: There are numerical and associative arrays [ass01]. They replace Maps and record data types which are part of other languages. Arrays are not homogenous.

We are starting with PHP 3. PHP 1 and 2 were only proof-of-concept versions for the programming language and never got used for real world applications; as far as I know. PHP 3 was the rewrite of the Zend people and got established in the web. Some developers might argue that PHP 5 was the first important release, because PHP 4 was only a quick & dirty scripting language. But I disagree. PHP drew attention in 2005 during the development of PHP 4 [com01].

Using these given paradigms, I was able to program my first website. Take some global data containers and call functions which operate on them globally. The order of function calls defines the content of the container in the end. Probably a last final function allows you to iterate over the container easily and produce the HTML output to be sent to the browser. Well, this works pretty well in PHP. But the major problems with imperative, procedural programming remains: You cannot rely on the content of global variables at any time. Separating different components to different levels of abstraction is impossible. Ask Niklaus Wirth for more information.

Functional style, Callbacks and list()

What about functional programming? We know that no language can be purely functional, but different languages provide different functional tools. One of the major requirements are functions as first-class citizens. Well, we don't have something like that until PHP 5.3 with the introduction of closures [lam01]. In previous versions, we have to create anonymous functions by string [cre01], which is damn slow and unreadable (there is no syntax highlighting in IDEs). As far as higher-order functions are primarily useful as callbacks, this is another issue in PHP, I would like to mention at this point. I always have to look up the notation of callbacks. An array with a reference to the object and the method as string. Seriously? [cal01]. Semantically an array is a container of somehow related elements. But it's not in contexts of callbacks (as one element relies on the existence of the other). Basic functional tools are provided by functions such as array_map, but they are useful in very few situations. Arrays are often associative and such functions destroy the indizes by converting the array to a numeric one. Furthermore unpacking (list()) is not possible in most situations [lis01] [lis02] and therefore list operations in PHP are a lot of pain. Hopefully, working with functions will be more pleasant with closures, but as far as I can see, the source code will get more unreadable and programs will be written in a very different style in future times (which is probably a bad thing).

There is one thing I like about PHP (in context of builtin functions), which is done more dynamic in python. In python you think of "take some names and bind them to any objects" [red01]. In PHP this is really a different thinking. It's more like "take some value and store it with an identifier". To sum it up, overwriting builtins is possible in python (which I was expecting) and overwriting builtins is not possible in PHP (which I was expecting). I am fine with both paradigms for the corresponding language. But somehow, there is some exception in PHP: If you want to use multibyte-safe functions out of the box, you want to call strlen() and PHP should automatically use the multibyte-safe version of this function (No, PHP has no builtin Unicode support). This can be achieved by setting the mbstring.func_overload parameter in the php.ini configuration file.

So the functional elements started in PHP 3 and received its major contributions in PHP 5. In PHP 4 the PHP Group decided to introduce object-oriented programming. In this release, OOP really sucked and the core developers decided to take a new approach in PHP 5 [oop01]. Sadly, they wanted to keep backwards compatible and new devs are confused whether or not to define constructors by class name or __construct (FYI, the latter). I really don't know what to write about object-oriented programming. Inheritance, Encapsulation, Polymorphism... you know the buzzwords. Yes, multiple inheritance is possible. Operator overloading is not possible (which is good in PHP, IMHO). Traits will be introduced in PHP 5.4 and most of the PHP software nowadays is written with this idea. Objects are a nice way to represent the world as it is; in source code. It helps you to create a good abstraction layer between the interface and the implementation. Libraries can be written efficiently and compatible to old versions. OOP in PHP was the new, correct way to go. Only few magic (primarily __get and __set) is supported, but I like it in this language. But some features are missing [nam01] [cla01].

But as always, some things are surprisingly stupid in PHP. Probably I am too stupid for this particular problem or I am using the wrong paradigm, but defining class properties is impossible [oop02]. References [ref01] are another issue I don't seem to understand [ref02] [ref03].

Type juggling

I will keep it short: I am sure that Rasmus thought a lot about type juggling, but I think it's a fail. PHP focuses on the web and user input validation is a primary issue in this regard. Type juggling is PHP's definition of being weak and dynamically typed. "4e" + 1 makes 5. I disagree with PHP's type system [typ01] [typ02] [typ03] [emp02] [swi01]. 1e4 is something the user might enter by accident and PHP will accept it as 10000. Javascript is also dynamically, weakly typed and has similar but not equal issues [jav01]. I accuse the type system to be the major backdoor in security concerns (which got highly discussed in PHP 4).

Compiler/interpreter design

JVM got really famous. Groovy, Clojure, JRuby, Jython... compiler developers seem to like this platform. I have never contributed to any of those projects, but I am really interested in the current developments of compilers; especially Python and its PyPy project [pyp01]. Almost any language existing more than 20 years has several implementations. Yes, I know there are more projects than the Zend Engine in PHP and the number of implementations is not a measurable factor, but I really cannot see any contributions of the PHP community to scientific and practical compiler improvements for the whole software industry. For me, it looks like "do what others have done some years ago". Reinvent the wheel (also from the language aspect). I am sure that there are exceptions, but I don't think, you can compare this to PyPy or the JVM. PHP is really not a playground or interesting field of interest for a theoretical computer scientist. With the introduction of fancy and magic features PHP became pretty powerful, but what? It's not that fancy and dynamic like ruby and mod_php is still more time-consuming than any other popular programming language implementation. If I want to optimize my programs and make them scalable, I am limited to a single container data structure and a lack of parallelism features.

I also have a problem with the interpreter's error messages [err01] [sta01] and cannot understand how particular problems are not resolved [emp01].

C syntax

I know. I dislike the C syntax. IMHO, it is verbose and source code cannot be read easily. Issues like dandling else's [dan01] have never been fixed in any derivate. PHP (just like a lot of other languages) extended the syntax for its own purposes and syntatic sugar. Well, not like Scala I think the core developers thought about all edge cases and fixed major issues. But minor issues remained and because they do not affect developers most of the time, they got part of the language. Examples include problems with the alternative syntax [alt01], the nested ternary operator [nes01], conditional expressions in short-curcuit evaluations [con01], optional code block parentheses [opt01] and optional call parentheses [cal02]. RegEx backslash escaping [reg01] and callbacks [cal01] are also things which are not very beautiful in PHP. With the introduction of closures, PHP resolves the latter the way other languages do.

Bad standard library

Another chapter I want to keep short: As anybody will know, the standard library is a collection of inconsistencies and a huge monster of backwards compatible code. Is it nl2br or nl_to_br? Is it idn2utf8 or is it idn_to_utf8? Is it str_len or is it strlen? Is it str_split or is it strsplit? I always have to look up the parameter order for strpos, in_array and most of the other string functions. It's partially okay to have an American parameter order in mktime; even though I do not agree with it. If you disagree with me about the stdlib, check out the internet for more "PHP sucks" articles on the web. Almost all of them mention the missing builtins naming conventions.

Unicode and PHP6

Another field I am new and not an expert in is Unicode. Unicode is the future. There is no doubt. And there is not doubt, that PHP sucks in this regard [uni01]. In comparison to other languages, PHP is primarly used to create output for the user... users in the web come from different countries and different backgrounds. Unicode is continuing to be improved all the time and no programming language can provide the full feature set of Unicode nowadays, but PHP does a really bad job in this matter.

PHP 6 is going to provide (full?) Unicode support. I assume it's going to be some Perl 6.

Conclusion

I am pretty sure, that you will disagree with some of my arguments. I am also sure that there are some aspects about PHP, you disagree. As you can see, my major problems with PHP are inconsistencies and boring concepts. PHP helped me to learn programming, but I cannot recommend it to other people. Life (and software) is going on, but for me without PHP. Goodbye!

[alt01]
Code Snippet, "PHP 020 alternative syntax fail",
/proj/snippets/php020.html [accessed 28th of Aug 2011].
[ass01]
Code Snippet, "PHP 021 associative and numerical indizes",
/proj/snippets/php021.html [accessed 24th of Aug 2011].
[cal01]
Code Snippet, "PHP 018 Callbacks",
/proj/snippets/php018.html [accessed 28th of Aug 2011].
[cal02]
Code Snippet, "PHP 006 optional call parentheses",
/proj/snippets/php006.html [accessed 14th of Sep 2011].
[cla01]
Code Snippet, "PHP 007 class property declaration",
/proj/snippets/php007.html [accessed 14th of Sep 2011].
[com01]
Tiobe Software, "Tiobe Programming Community Index",
http://www.tiobe.com/content/paperinfo/tpci/images/tpci_trends.png [accessed 21th of Aug 2011].
[con01]
Code Snippet, "PHP 004 conditional expression via SCE",
/proj/snippets/php004.html [accessed 28th of Aug 2011].
[cre01]
The PHP Group, "PHP: create_function",
http://us2.php.net/create_function [accessed 28th of Aug 2011].
[dan01]
Code Snippet, "PHP 019 Dandling else",
/proj/snippets/php019.html [accessed 28th of Aug 2011].
[emp01]
Code Snippet, "PHP 001 empty() behaviour",
/proj/snippets/php001.html [accessed 14th of Sep 2011].
[emp02]
Code Snippet, "PHP 013 empty('0')",
/proj/snippets/php013.html [accessed 14th of Sep 2011].
[err01]
Code Snippet, "PHP 005 error message of type hinting",
/proj/snippets/php005.html [accessed 14th of Sep 2011].
[jav01]
Ivo Wetzel and Zhang Yi Jiang, "Javascript Garden",
http://bonsaiden.github.com/JavaScript-Garden/#types [accessed 30th of Aug 2011].
[lam01]
Fabien Potencier, "On PHP 5.3, Lambda Functions, and Closures - Fabien Potencier",
http://fabien.potencier.org/article/17/on-php-5-3-lambda-functions-and-closures [accessed 30th of Aug 2011].
[lis01]
Code Snippet, "PHP 023 list() in foreach",
/proj/snippets/php023.html [accessed 30th of Aug 2011].
[lis02]
Code Snippet, "PHP 025 list() language construct",
/proj/snippets/php025.html [accessed 30th of Aug 2011].
[nam01]
Code Snippet, "PHP 027 Named parameters",
/proj/snippets/php027.html [accessed 14th of Sep 2011].
[nes01]
Code Snippet, "PHP 009 nested ternary oeprator",
/proj/snippets/php009.html [accessed 28th of Aug 2011].
[oop01]
The PHP Group, "Classes and Objects",
http://us2.php.net/manual/en/language.oop5.php [accessed 24th of Aug 2011].
[oop02]
Code Snippet, "PHP 022 class properties",
/proj/snippets/php022.html [accessed 25th of Aug 2011].
[opt01]
Code Snippet, "PHP 016 optional code block parentheses",
/proj/snippets/php016.html [accessed 28th of Aug 2011].
[pyp01]
The PyPy Project, "PyPy",
http://pypy.org/ [accessed 30th of Aug 2011].
[red01]
Code Snippet, "Python 002 redefining True and False",
/proj/snippets/py002.html [accessed 30th of Aug 2011].
[ref01]
The PHP Group, "References Explained",
http://www.php.net/manual/en/language.references.php [accessed 24th of Aug 2011].
[ref02]
Code snippet, "PHP 036 References in class properties",
/proj/snippets/php036.html [accessed 28th of Aug 2011].
[ref03]
Code snippet, "PHP 017 references implementation fail",
/proj/snippets/php017.html [accessed 14th of Sep 2011].
[reg01]
Code Snippet, "PHP 012 regex backslash escaping",
/proj/snippets/php012.html [accessed 28th of Aug 2011].
[sta01]
Code Snippet, "PHP 026 Static call of non-static method",
/proj/snippets/php026.html [accessed 14th of Sep 2011].
[swi01]
Code Snippet, "PHP 024 switch statement loose comparison",
/proj/snippets/php024.html [accessed 30th of Aug 2011].
[typ01]
The PHP Group, "PHP: Types",
http://us2.php.net/manual/en/language.types.php [accessed 24th of Aug 2011].
[typ02]
Code Snippet, "PHP 008 type comparison",
/proj/snippets/php008.html [accessed 24th of Aug 2011].
[typ03]
Code Snippet, "PHP 028 Type juggling in array keys",
/proj/snippets/php028.html [accessed 174th of Sep 2011].
[uni01]
Code Snippet, "PHP 011 Unicode incapability",
/proj/snippets/php011.html [accessed 30th of Aug 2011].