

What are the crawling horrors of PHP? - lox
http://www.quora.com/What-are-the-crawling-horrors-of-PHP

======
WilliamLP
I believe this author just doesn't like PHP and doesn't consider that some of
these "weaknesses" are actually strengths in the eyes of many. Some of the
points are fair, but never show-stoppers, _for the domains that PHP is used
in_. You're not going to want to write general purpose or especially heavy
duty low level algorithmic code in PHP. It's a web/database glue language at
heart.

> # Arrays and hashes treated as the same type

We like this! More specifically, there is no "array"; they are manufactured as
dictionaries with integer keys. In practice this works fine, and it's not even
algorithmically different, since a hash access is a constant time operation.

> Hash syntax versus class syntax - i.e. $key['value'] versus $key->value

We like this a lot! $array['key'] will access a dictionary. We know it's not
going to go through things like subclass rules and overrides, the way an
access would in JavaScript, avoiding one of the worst parts of the language,
including having to use "hasOwnProperty" for rigorous code.

> # Functions/methods always require parenthesis

Yes, and it's really not clear to me that the "cure" is better than the
disease here, and this comment seems a little out to lunch. The standard
practice I would think would be to not expose a $person->first_name variable
directly in the first place. If you want an object with a flexible key-value
coding system, you're free to write one. (And you can override dictionary
access [] if you like.)

> No macros

I tremble.

> Writing an array literal requires literally writing out the characters a, r,
> r, a, y, ( and ).

Oh boo-hoo. Comments like like this, to me, separate out perfectly the
programmers who are interested in getting something done versus seeking a sort
of pursuit of academic idealism for its own sake. I can tell he only just
managed to resist saying it has braces and semicolons too.

> It depends what version of PHP.

Use PHP 5.

> How do you delimit HTML from output PHP code? <?, ?>, <?php ?>, <% %>? Well,
> it depends on some global setting in php.ini.

Use <?php ?> always.

> PHP doesn't have multiple inheritance, fine, but it doesn't have
> mixins/modules, either.

We do not want! Locality of code is worth more to us, especially for those of
us who have tried to navigate a maze of categories in an unfamiliar
Objective-C codebase or something like that.

> If you do enable PHP's E_ALL warnings, you get warnings and errors for all
> kinds of crazy things you don't want warnings for.

You're wrong, you really do want those warnings. If you want to turn off
deprecated warnings for legacy PHP4 code, you should make that explicit.

> PHP is exceptionally slow unless you install a bytecode cache such as APC or
> eAccelerator.

So when it isn't fast enough by default (and it usually is), do that.

> People often abuse include(). Rather than using it to pull in functions and
> classes, they use include for actual code execution,

Like in a template mechanism, which is a legitimate use for it.

> Because it is designed to be run in the context of Apache, PHP doesn't work
> very well as a command-line scripting language,

A hammer doesn't drive screws very well.

> There is a lack of standards and conventions.

This is called flexibility. You can code within CakePHP or Zend Framework if
you want conventions.

> There are a variety of ORMs available all of which suck in different ways,

This is not just a PHP problem:)

~~~
avar
>> # Arrays and hashes treated as the same type > We like this! [...]

Maybe you do. But I've always found it annoying.

> In practice this works fine, and it's not even algorithmically different,
> since a hash access is a constant time operation.

It is actually. Read the array.c and zend_hash.c code. It's only a constant
time operation if you're not interested in the difference between whether a
hash key actually exists, or whether it exists and its value is set to NULL.
The former is O(n) if you use array_key_exists. From zend_hash_exists:

    
    
        while (p != NULL) {
            if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
                if (!memcmp(p->arKey, arKey, nKeyLength)) {
                    return 1;
                }
            }
            p = p->pNext;
        }
        return 0;
    

>> PHP doesn't have multiple inheritance, fine, but it doesn't have
mixins/modules, either.

> We do not want! Locality of code is worth more to us

Code that I'd write in Common Lisp or Perl that takes advantage of multiple
inheritance and the composition it offers is a lot uglier in PHP when I have
to hack around not having multiple inheritance. It leads to bigger and
monolithic classes that you can't easily compose.

>> Because it is designed to be run in the context of Apache, PHP doesn't work
very well as a command-line scripting language,

> A hammer doesn't drive screws very well

This is actually a major problem with PHP. Unlike Perl, Python, Ruby, Lisp
etc. you can't easily run most PHP code persistently, so the execution model
for most applications is to parse, compile and execute the application for
each request.

You can get around that in some cases, but some core language features have
been blocking this until relatively recently. E.g. create_function() would
always leak memory, but in 5.3 PHP finally has support for anonymous
functions.

~~~
WilliamLP
> It is actually. Read the array.c and zend_hash.c code. It's only a constant
> time operation if you're not interested in the difference between whether a
> hash key actually exists, or whether it exists and its value is set to NULL.

That's weird, and does seem like a wart. But is this really a problem in
practice that leads to performance difficulties in real code? (This is not a
snippy rhetorical question, I'd be interested in a real world example.) It
seems to me that if I'm using a PHP dictionary as an array, I'd know the
length, and thus I'd be guaranteed that any access exists.

I also like that arrays being dictionaries gives me the ability to do
foreach($array as $index=>$value) if I want, which is nicer than some other
languages, though admittedly some dynamic languages do such things better.

> Code that I'd write in Common Lisp or Perl that takes advantage of multiple
> inheritance and the composition it offers is a lot uglier in PHP when I have
> to hack around not having multiple inheritance. It leads to bigger and
> monolithic classes that you can't easily compose.

This is a holy war, obviously, and you do get interfaces at least. It suffices
to me to know that I do have some intelligent supporters on the side of
disliking multiple inheritance and mixins very much. If you're one of the
people who can be extremely productive building large programs in a Lisp
style, much respect and power goes to you, and anyone has to concede that PHP
will be too limiting in that case.

> This is actually a major problem with PHP. Unlike Perl, Python, Ruby, Lisp
> etc. you can't easily run most PHP code persistently, so the execution model
> for most applications is to parse, compile and execute the application for
> each request.

Agreed, and it is a huge pain when you want to do something after a request
but yet you don't want to tie up the user in the mean time.

I'm not sure I'd want PHP to be a language that makes it easy to have a
persistent execution model though; that simplicity (and restriction) is one of
the things that has made the language so popular and scalable. PHP's model
_usually_ works fine for the kind of web-based problems it's intended for.

~~~
avar
> That's weird, and does seem like a wart. But is this really a problem in
> practice that leads to performance difficulties in real code?

Here's some code I wrote in 2005 that ran into this issue:
<http://www.mediawiki.org/wiki/Special:Code/MediaWiki/10549>

> It seems to me that if I'm using a PHP dictionary as an array, I'd know the
> length, and thus I'd be guaranteed that any access exists.

The use case is the common idiom of populating a hash, and then iterating
other hashes and checking if their keys exist in the original.

In the example above I was loading ~50 files with 1000 key hashes each to
check if there were any leftover translation strings in the translated files
that weren't in the English original.

Because the values could never be NULL I could get away with not using
array_key_exists() which reduced the runtime from 60 to 2 seconds. But it's
pretty silly that the core datastructures of the language have pitfalls like
these.

>> This is actually a major problem [...]

> Agreed, and it is a huge pain when you want to do something after a request
> but yet you don't want to tie up the user in the mean time.

> I'm not sure I'd want PHP to be a language that makes it easy to have a
> persistent execution model though; that simplicity (and restriction) is one
> of the things that has made the language so popular and scalable. PHP's
> model usually works fine for the kind of web-based problems it's intended
> for.

In some ways, especially the built-in template language. But overall I think
PHP as a isn't simple or newbie friendly at all. Its main advantage was that
it offered a really simple execution model + Apache module. Which ISPs and
others could easily offer along with MySQL, with little administration time
compared to offering equivalent shell services.

It was also was one of the first to have friendly online documentation with
lots of syntax highlighted example code, and comments where people could
submit more examples.

But as a language it was never very competitive, and due to some of the
tradeoffs made PHP never acquired a real community of module writers and re-
usability. Thus most large PHP code bases end up being big balls of mud
compared to equivalent code written with Catalyst, Django or even Rails.

These days it seems to be mostly heading for being a worse Java with more
bugs. Unless you have existing code in PHP other languages are probably a
better fit for web applications these days.

------
nuclear_eclipse
Some of these complaints don't even make sense:

He doesn't like the lack of strict mode, but complains that E_ALL tells him
too much; maybe it's telling him too much because he's not writing things
correctly, just like 'use strict' would.

He complains that you need to remember the parenthesis for a function call,
but short of Ruby, I can't think of any other "normal" language that doesn't.
C/C++/C#, Java, Python...

He complains that a whole bunch of things are considered false, but when using
the === operator, they aren't.

Always use <?php ?>, and your code will always work, everywhere.

Just because people abuse include() doesn't make it a flaw of the language.
Strawman ftw.

Plugins written for one framework won't work in another. Gasp! News at 11...

~~~
adamc
Python has properties to abstract away function calls.

~~~
nuclear_eclipse
So does PHP:
[http://www.php.net/manual/en/language.oop5.overloading.php#l...](http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members)

------
greenlblue
Is there any point to this kind of discussion? These kinds of questions have
maximum entropy, i.e. if you put a monkey at a keyboard and let it bash the
keyboard I bet these are the kinds of questions you would get. One can type up
questions of the form "What is horrible about X?" ad museum and not be any
closer to creating any kind of value in any form whatsoever.

~~~
bad_user
It's not the question that's relevant, it's the answers.

~~~
forcetenhen
And as usual it'll end up with the same old list of reasonable problems,
'unforgivable' omissions and miles upon miles of ridiculous hyperbole. It's
started already. Is abuse of includes or goto an inherent problem of PHP? I
was abusing includes 15 years ago when I messed with C and my earliest BASIC
was the code equivalent of snakes & ladders.

All this kind of thing tends to do is embolden the snobs, put the backs up of
the faithful and be of no practical use to any reasonable person looking for
honest answers. It doesn't even have the virtue of being a humourous
discussion since it's been flogged to death over the whole internet for a
decade.

~~~
regularfry
Just to pick on the includes example, I think it's fair to point it out as a
deficiency if there exist other languages and environments which
enable/encourage/force you to get it right. It's not a defence that other
languages also get it wrong.

------
lox
Most of these gripes are fixed in PHP 5.3, although the lack of ability to
access $this in closures drives me nuts. Aside from that, all languages have
minor syntactic issues. Take your pick.

I think the far bigger problem with PHP comes from the culture that surrounds
re-use. Writing re-usable PHP is hard, we lack decent package management
systems and systems for distributing light-weight packages of code with simple
dependancies (I'm looking at you PEAR).

The end result is a culture where re-inventing the wheel is standard practice
or at best copy and paste.

------
RyanMcGreal
There's plenty to hate about PHP, but most of my gripes have been repeated ad
nauseam all over the internet. Yet one issue that really drives me bonkers
doesn't seem to have received the opprobrium it deserves: _Functions can take
default named arguments, but insist on referencing named arguments by order,
not name._ This is just utterly asinine.

~~~
nuclear_eclipse
That's because PHP is heavily influenced by C and Perl, both of which exhibit
the same behavior.

~~~
RyanMcGreal
What's the point of named arguments if you can't do something like the
following (e.g. Python)?

    
    
        >>> def some_func(a=1, b=2, c=3):
            return (a + b) * c
    
        >>> val1 = some_func()
        >>> val1
        9
        >>> val2 = some_func(b=3)
        >>> val2
        12
        >>> val3 = some_func(c=5)
        >>> val3
        15
        >>>

~~~
nuclear_eclipse
I completely agree with you, and I much prefer Python's method of handling it.
I was at explaining why PHP acts the way it does.

~~~
RyanMcGreal
Yes, of course. I wasn't holding you responsible. :)

------
dfox
Is there any reason for this: "If a function returns an array, you have to
assign it to a variable before accessing an element, you can't just add an
index after the function call." ? I cannot grasp why PHP's authors "designed"
it this way.

~~~
troels
PHP's parser/syntax is a bit of a mess. I'm guessing it could incur some sort
of inconsistency.

~~~
randallsquared
Yeah, this is one of the most annoying things about PHP for me. Another
similar one is that you can't use empty() on the result of a function call
without assigning it to a variable first, and the error you get is something
about an invalid write context, which is pretty opaque if you don't just
happen to know what it means already.

------
FiReaNG3L
# Arrays and hashes treated as the same type

For me this is an advantage over other languages. I'm looking at you, Perl.

~~~
avar
It's not just Perl, every language I've seen or heard of except PHP has a
clear distinction between its unordered key-value datatype, and an array
datatype. That includes Python, Lisp, Lua, and others.

PHP has a Frankensteinian mix between the two. You /can/ implement it in any
other language by just keeping an array along with your hash that indicates
the order in which elements were inserted:
<http://search.cpan.org/perldoc?Tie::StoredOrderHash>

But you almost never want to do this. I've only used it once in all the PHP
code I've written. And having to deal with the ambiguity of PHP's key-value
array datatype wasn't worth it elsewhere wasn't worth that.

~~~
scotty79
Actually PHP arrays are ordered dictionaries. Python got standard
implementation of this kind of collection type just recently.

This 'Frankensteinian mix' is the most versatile collection type I have seen
so far and I attribute large part of PHP success to having this as first
choice when in need to keep collection of elements.

You can build vector, list, stack, tree, map without even knowing what those
are just confronting what abilities you require with what PHP arrays can do.

------
Goladus
I don't have much experience with PHP, so I don't hate it and curse the people
who inflict it on me the way I curse, say, perl programmers. My complaints are
basically: I tried it once and didn't like it. It was hard to write the
abstractions I wanted and the results were buggy. It could just be me.

Several years ago I wrote a feature simultaneously in Python, Perl, and PHP.
It was a fairly simple task-- retrieve a list of formatted strings, parse the
data with regular expressions, and transform the 3-dimensional information
into a 2-dimensional table.

In the python version, the regexp functions were ugly, but idiomatic and also
separated into independent functions. The logic was clear and 3 years later
it's still easy to understand what it's doing.

I can't find the perl version, but I remember having to use a retarded
workaround because references weren't working as documented in one tiny (but
essential) edge case. Basically I had to duplicate the entire program to
handle two different cases. There is was probably some completely different
strategy that would work better, but I didn't have three days to spend digging
through perl docs to find it.

In the PHP version, I seem to have had some trouble using abstractions. The
program is just one monolithic while loop with some comments. Also, I see some
weird hacks in the PHP version and I don't remember why I had to use all of
them. At one point I'm populating an array with empty values using
'array_fill()' and I see some temporary-looking variable names like
$start_end, and there are a bunch of comparisons to arbitrary index values.
For example $start_end[1] is 'start' and $start_end[2] is 'end'. There's none
of this crap in the python version.

Ultimately I went with the PHP version. Because the rest of the app was
already written in PHP it was far easier to deploy. A year later the feature
broke for some reason and I never had the time to fix it.

So ultimately, I would probably tend to avoid PHP in the future because it
doesn't seem to support my style of programming very well and I don't see many
advantages to indoctrinating myself to its quirks.

~~~
shaunxcode
can you post the code in a pastebin or is it proprietary/too involved w/ rest
of the system to make sense in isolation?

------
kls
_There are at least three ways of handling errors - return codes,
trigger_error(), and exceptions, all of which are handled differently and used
inconsistently by functions and libraries, and require messing with various
combinations of global settings to cause errors display or not display to the
user. There are furthermore no agreed-upon conventions for handling errors, so
libraries freely mix all of these methods along with directly printing errors
to the output which is impossible to trap._

For me this was a show stopper for using PHP for anything other than
maintaining existing stuff that we inherit (and only for clients we really
like).

error handling is at its core a foundation to quality, without proper error
handling you have to put in significant effort to build a quality product
because the structure has to be reinforced at every level. Having multiple
ways to handle errors is almost worse than having none at all. This is one
area that really needs to be standardized and have "the one way" to do it.
Good or bad, it allows everyone to know what to expect.

It is just my opinion but, this one flaw makes PHP one of the worst languages
I have ever use, which is sad because Wordpress and Drupal are great products
but I can't stand to have to work in PHP, if I have a project that I know will
not require custom development, I use Wordpress or Drupal I really wish they
supported alternative languages for writing custom modules,It would be nice to
be able to write them in Python or hell even JavaScript has proper error
handling.

------
scotty79
I'm extremely annoyed about how there is no native datatypes for HTML and SQL
and they are just plain strings and are allowed freely to be created from
strings glued together with any arbitrary data without any default escaping
what leads to SQL injections and XSS attacks.

Oh wait. That's true for (almost?) all languages that are used to writing
webapps.

------
ErrantX
_There are a variety of ORMs available all of which suck in different ways,
such as bloated syntax, forcing you to write SQL statements as a bunch of
function calls (i.e. $something- >select('column')->where('condition >
0')->...), or excessive configuration. The one decent ORM (DMZ Datamapper:
<http://www.overzealous.com/dmz/>) is maintained by one person, and limited to
the Code Igniter framework._

This is a complaint I'v made before... Currently I am using Jelly [1] for the
Kohana framework and it is wonderful compared to most of the PHP ORM
offerings.

1\. <http://jelly.jonathan-geiger.com/>

~~~
shaunxcode
hah [http://jelly.jonathan-
geiger.com/docs/api/Jelly_Field_Behavi...](http://jelly.jonathan-
geiger.com/docs/api/Jelly_Field_Behavior) \- I wanted to see what his approach
was in regards to defining custom types etc.

~~~
ErrantX
Uh, there is no class Jelly_Field_Behaviour, instead you need to look at the
various classes in Jelly_Field_Behaviour_* - I don't know where it linked you
to that but it was obviously in error.

Here are the behaviours: [http://github.com/jonathangeiger/kohana-
jelly/tree/master/cl...](http://github.com/jonathangeiger/kohana-
jelly/tree/master/classes/jelly/field/behavior/)

~~~
shaunxcode
Thanks, if I can find where I got that link I'll try and ping the owner on
github.

------
mildweed
I thought this was going to be an article about the difficulties in writing a
web spider in PHP (which is not PHP's strong suit).

I once wrote a crawler loosely based off Snoopy
(<http://snoopy.sourceforge.net/>) and it was a nightmare.

------
bhiggins
One problem is that the people in charge of PHP and their ongoing bad choices.

~~~
revolvingcur
Yeah. I'm cherry-picking here, but if the creator of the language says
something like the following, it's probably a bad sign.

"I'm not a real programmer. I throw together things until it works then I move
on. The real programmers will say 'yeah it works but you're leaking memory
everywhere. Perhaps we should fix that.' I'll just restart apache every 10
requests."

But because that could sound like either DHH or Rasmus Lerdorf, there's also
this:

"I have absolutely no idea how to write a programming language, I just kept
adding the next logical step on the way."

The lack of overall direction and ball-o-mud hackery is exactly what one would
expect to underlie PHP in its present state.

~~~
robryan
It's a feature though, it's not like there aren't web development languages
that have been designed in a much beter way. I think it's good to have one
from the "it get's the job done" mindset.

