|
Okay. I need to set the record straight. I'm not saying PHP is a bad langauge. Despite all the hails of greatness that I don't understand (except as to write-off these people as either C-philes or lacking in experience with good languages like Ruby or Objective-C), I still think PHP is useful and good at what it does. So let's spend a few moments on what I'm not trying to say before I delve into what I do want to say.
PHP is very good at what it was designed to do. As this article on the history of PHP outlines, PHP started out as nothing more than as essentially making C for CGI. More precisely, a C like langauge that is tailor made for, and includes libraries for, making CGIs easily. PHP has more than succeeded at this.
Starting with PHP 3, and only mildly updated in PHP 4, was objects. From what I understand, objects started out as just being syntactic sugar for associative arrays and that the creators of PHP really didn't plan on anyone using objects for much. From my personal experience, PHP 4 did little to get past this. Objects were still only marginally more useful (and more of a pain in the ass to code) than using associtive arrays and function libraries to act on them.
PHP 5, of course, fixed all this, and so, knowing the history and the intent, I don't blame the makers of PHP for the ueslessness of objects up to that point. I also don't blame them for the extensive API not having a single object in them.
PHP just isn't an object oriented langauge. It is a C-style scripting language that happens to have just gotten objects added on top.
So what is it, then, that I dislike so much about PHP? Simply put, despite all the time they put in to the new Zend Engine, they didn't fix what I considered to be their biggest flaw in their Objects: the unnecessary required overuse of the $this keyword. As I will demo with a simple code snippet below, the syntax for PHP is so much more cumbersome and hard to read than any other object oriented language I know, that I nearly went insane while trying to write real code this way.
As a simple example of the kind of thing I run into, let's visit everyone's favorite example class, Point. I am going to start by giving a code fragment for a distance from point member function for this class in both the Ruby and PHP language, though you can click here and here to see the full Ruby and PHP source respectively. Essentially, this function uses the instance variables of the called upon Point class instance, and calculates the distance to the passed point p using the distance function.
| Ruby |
def distance_from_point( p ) return Math.sqrt( (@x-p.x)*(@x-p.x) + (@y-p.y)*(@y-p.y) ) end |
| PHP |
function distance_from_point( $p ) { return sqrt( ($this->x - $p->x)*($this->x - $p->x) + ($this->y - $p->y)*($this->y - $p->y) ); } |
One should be able to immediately see my frustration. If not, I'll explain it to you: I had to type "$this->" in front of each instance variable, which is very cumbersome when trying to implement many functions, most especially math related functions! This cumbersom writing also makes these functions incredibly difficult to read compared to the much kinder version written in Ruby. I mean, imagine having to maintain this code if someone else wrote it! I certainly wouldn't like to be the one who has to maintain that!
Although not nearly as poignant an example, the problem also exists when calling an isntance method from within other instance methods. For example, if I wanted to implement a method for calculating the distance the point is from the origin, it would probably be a good idea to use the aboce distance_from_point function, passing it a new instance of Point with the coordinates (0,0). Below is what that code would look like for both langauges.
| Ruby |
def distance_from_origin return distance_from_point( Point.new(0,0) ) end |
| PHP |
function distance_from_origin() { return $this->distance_from_point( new Point(0,0) ); } |
In this case, the extra use of $this in PHP isn't nearly as distracting, but imagine if you have a routine with a lot of delegating to other member functions, or even worse, delegating to method calls in composite objects!
In the end, every other language I have ever worked with is smart enough to resolve the scope of instance variables and functions all by itself. Unfortunately, PHP wasn't constructed smartly enough to do this, thus requiring the use of $this to resolve the scope for it. Furthermore, now that so much code is written around this unfortunate choice of scoping rules, a fix to the PHP language would destroy the backwards compatability of the code written thus far. And thus it doesn't look like I'll bother with using classes in my PHP code anytime soon.
(c)2005, Jeff Reinecke. |