Hacker News new | past | comments | ask | show | jobs | submit login

I wish bloggers would stop quoting that fractal article. At least 50% of what's written in there is totally wrong/false. Other information is terribly out of date. And even more information is merely half-truths and lack of understanding of the language. The article author clearly scanned through PHP bashing articles and took material from them verbatim; mistakes and all.

I'm not going to argue that PHP is a great language, but the article is a complete disservice to anyone who has bothered to read it. I'm disappointed, but not surprised, that Jeff Atwood linked to it.

Just a few errrors in that article:

> Operators are very fragile in the parser; foo()[0] and foo()->method() are both syntax errors. The former is allegedly fixed in PHP 5.4, but I can’t find mention of a fix for the latter.*

The latter doesn't need a fix because it always worked. Honestly, how hard is it to test that foo()->method() works?

> Objects compare as greater than anything else… except other objects, which they are neither less than nor greater than.

Strict-equals on objects compares the references; but regular equals compares the contents of the objects. Two objects compare equal if the contain exactly the same fields and values. Seems pretty reasonable to me.

> + is always addition, and . is always concatenation.

This is a good thing; JavaScript gets this wrong.

> There is no way to declare a variable. Variables that don’t exist are created with a null value when first used.

Variables that don't exist issue a notice. You can deal with that just like any other error.

> Global variables need a global declaration before they can be used.

Actually there is also the $GLOBALS array for this. I'll agree that's not much a solution. Globals should just not be used; if you want to use static class variables, it's a much better choice with a sane syntax.

> there’s no pass-by-object identity like in Python.

I'm not sure if I understand this but all objects are passed-by-reference in PHP (since 5) and PHP references act appropriately when used as function parameters, etc.

> A reference can be taken to a key that doesn’t exist within an undefined variable (which becomes an array). Using a non-existent array normally issues a notice, but this does not.

An attempt to use the reference will result in a notice but isset() and empty() operate it on it correctly.

> Constants are defined by a function call taking a string; before that, they don’t exist.

You can declare constants in classes and namespaces with the const keyword.

> There’s an (array) operator for casting to array. Given that PHP has no other structure type, I don’t know why this exists.

You can cast scalars to single element arrays and objects to arrays with the same structure. Both are actually very useful.

> include() and friends are basically C’s #include: they dump another source file into yours. There is no module system, even for PHP code.

PHP is interpreted -- namespaces and autoloaders are PHP's module system.

> Appending to an array is done with $foo[] = $bar

This is a good thing.

> empty($var) is so extremely not-a-function that anything but a variable,

Empty is equivalent to the not operator but will also work on undefined variables -- that's why it requires a variable.

> There’s redundant syntax for blocks: if (...): ... endif;, etc.

Useful inside of templates where matching { } is much more difficult.

> PHP’s one unique operator is @ (actually borrowed from DOS), which silences errors.

Sometimes you don't care if a function succeeds; like with the unlink() function which will raise an error if the file you're trying to delete doesn't exist.

> PHP errors don’t provide stack traces.

Not true. Debug_backtrace() will give you a stack trace in an error handler.

> Most error handling is in the form of printing a line to a server log nobody reads and carrying on.

Assuming, of course, the programmer doesn't do anything to handle errors.

> E_STRICT is a thing, but it doesn’t seem to actually prevent much and there’s no documentation on what it actually does.

E_STRICT (or lack of it) is for compatibility with PHP4. When enabled it will "warn you about code usage which is deprecated or which may not be future-proof." -- quote from the manual.

> E_ALL includes all error categories—except E_STRICT.

Unfortunate naming here -- E_ALL is from PHP4 and prior and E_STRICT is all about PHP5. Including it in E_ALL would break PHP4 scripts running on PHP5.

> Weirdly inconsistent about what’s allowed and what isn’t.

This author is confused why syntax errors would be parse errors but logic errors are not.

> PHP errors and PHP exceptions are completely different beasts. They don’t seem to interact at all.

This is sort of true; PHP errors and exceptions exist in different universes but it's easy to unify them and PHP even provides a built-in exception ErrorException to do so. You can turn every PHP error into an exception with 4 lines of code complete with stack traces. You could even turn exceptions into errors but I wouldn't recommend that. PHP supports both procedural and OO programming styles -- this is not a bad thing.

> There is no finally construct

C++ also doesn't have a finally construct. But C++ and PHP support RAII -- class destructors run when the stack is unwound so you can do your cleanup. Finally would be a welcome addition to both languages.

> function foo() { return new __stdClass(); } leaks memory. The garbage collector can only collect garbage that has a name.

PHP is reference counted with a cycle-detecting GC. That would not leak memory.

> Function arguments can have “type hints”, which are basically just static typing. But you can’t require that an argument be an int or string or object or other “core” type

This is true, but it's an ongoing discussion on how to correctly handle scalar type hints. For all the discussion about how PHP isn't designed the author takes issue with the thing they're taking their time on.

> Closures require explicitly naming every variable to be closed-over. Why can’t the interpreter figure this out?

Because of the dynamic abilities of PHP, there is simply no way for the interpreter to ever figure out the variable to close over. The solution is actually a rather simple.

> clone is an operator?!

Of course!

> Object attributes are $obj->foo, but class attributes are $obj::foo. I’m not aware of another language that does this or how it’s useful.

C++ does it. $obj::foo doesn't make any sense, if you're accessing class attributes then you use the class name Class::foo.

> Also, an instance method can still be called statically (Class::method()). If done so from another method, this is treated like a regular method call on the current $this. I think.

Only static methods can be called statically. The other calling methods statically is similar to C++ ... you can call parent class methods explicitly by name by-passing any overriding.

> new, private, public, protected, static, etc. Trying to win over Java developers? I’m aware this is more personal taste, but I don’t know why this stuff is necessary in a dynamic language

This is personal taste not a valid critique.

> Subclasses cannot override private methods.

That is the definition of private methods!

> There is no method you can call on a class to allocate memory and create an object.

You can use reflection to create an object without calling the constructor.

> Static variables inside instance methods are global; they share the same value across all instances of the class

This is the definition of a static property!

> Yet a massive portion of the standard library is still very thin wrappers around C APIs

That is, in fact, the point. PHP is supposed to be a thin scripting language layer over C. It's expanded beyond that. Many of the poor naming conventions are not because of PHP but rather are the exact API of the underlying C library.

> Warts like mysql_real_escape_string, even though it has the same arguments as the broken mysql_escape_string, just because it’s part of the MySQL C API.

Both the C API and PHP have both these functions for backwards compatibility reasons. This entire API is pretty much depreciated with both the mysqli library and PDO replacing it.

> Using multiple MySQL connections apparently requires passing a connection handle on every function call.

Yes, exactly. That's the only way multiple connections could possibly work.

> PHP basically runs as CGI. Every time a page is hit, PHP recompiles the whole thing before executing it.

Unless you use a free code cache like APC. It will eventually be built in. Most people don't need it.

> For quite a long time, PHP errors went to the client by default

If you don't handle your errors, they go somewhere.

> Missing features

Most of these are provided by frameworks just as they are in Python, Ruby, C#, etc.

> Insecure-by-default

Most of these things are now removed from the language after being depreciated for years.




I stopped reading the blog article when I read the complaints around "private" and "static". The behavior is exactly what they were intended to. If he doesn't want that, he shouldn't use them. It also implies that he doesn't have much experience with languages like C#, Java or C++. Otherwise he would have learned this already.


Or I think they're misfeatures everywhere.


Then you should have mentioned it. From the article it seems that you are talking specifically about PHP, when in reality that argument can be applied to many.

I can only make my assumptions based on what I read. The lack of references to other languages makes me doubt your experience, and that is essential when you criticize something.

PHP has flaws and you have some valid points, but when you mention things that are either not specific to PHP or not a problem for me it makes me more skeptical.


Come on, the guy is right about a lot of things. But as he said, there are things about any language that he hates. What's the big deal? Defame php all you want, I won't defend it, I just use it!


> Strict-equals on objects compares the references; but regular equals compares the contents of the objects. Two objects compare equal if the contain exactly the same fields and values. Seems pretty reasonable to me.

The line you quoted is talking about ordering, not equality.

> This is a good thing; JavaScript gets this wrong.

It IS a good thing, but it stands out when most of the language is extremely weakly-typed and even the original manual claims that separate operators for strings and numbers are confusing.

> I'm not sure if I understand this but all objects are passed-by-reference in PHP (since 5) and PHP references act appropriately when used as function parameters, etc.

So some things (objects) are passed by reference implicitly, and some (all else) are not. Yikes!

> You can declare constants in classes and namespaces with the const keyword.

Okay. Why not at top-level?

> You can cast scalars to single element arrays and objects to arrays with the same structure. Both are actually very useful.

You've practically invented a bug right there: if I write a function that can take either one value or an array of items, and you pass in a single object, I'll get a useless keyed array of its attributes.

> PHP is interpreted -- namespaces and autoloaders are PHP's module system.

What does being interpreted have to do with anything? Python and Perl are bytecode-interpreted (not positive about Ruby) and they both have rich module systems that don't require any fussing around. Heck, shell is interpreted, but zsh manages something almost like modules.

> Empty is equivalent to the not operator but will also work on undefined variables -- that's why it requires a variable.

Why does it need to look like a function when it clearly isn't one? return and echo don't.

> Useful inside of templates where matching { } is much more difficult.

In theory, but I've never seen any actual PHP code that uses them.

> Sometimes you don't care if a function succeeds; like with the unlink() function which will raise an error if the file you're trying to delete doesn't exist.

That's what exception handling is for -- unfortunately, PHP errors are an entirely separate beast from PHP exceptions.

> Not true. Debug_backtrace() will give you a stack trace in an error handler.

I said "PHP errors don't provide stack traces", and you aren't disputing that. Your own code can muck around to give you a stack trace (in most cases), yes, but the runtime doesn't do it for you.

> Assuming, of course, the programmer doesn't do anything to handle errors.

Defaults are important. I sure have a lot of people telling me it's great that PHP does web stuff out of the box -- why is it not then bad that PHP doesn't help you fix errors out of the box?

> E_STRICT (or lack of it) is for compatibility with PHP4. When enabled it will "warn you about code usage which is deprecated or which may not be future-proof." -- quote from the manual.

Yes, and that doesn't describe what it does. You can't tell what it's for, either: it's clearly not for compatibility with just PHP4, because even the PHP 5.4 release notes mention the addition of a new E_STRICT. Yet I can't be sure on what parts of the language actually ARE deprecated without reading the entire manual looking for mentions of E_STRICT.

> This author is confused why syntax errors would be parse errors but logic errors are not.

Read more carefully; the two lists are written roughly in parallel. A bogus object attribute gets a warning, but a bogus class attribute is a fatal error. (Not an exception, either, so you can't catch it with the exception handling that the OO system is supposed to be using.) A string value stored in a variable can be called, but the same string value as a literal cannot. And so on.

> This is sort of true; PHP errors and exceptions exist in different universes but it's easy to unify them and PHP even provides a built-in exception ErrorException to do so. You can turn every PHP error into an exception with 4 lines of code complete with stack traces.

Neat, though my understanding is that this still doesn't work with fatal errors, which are shockingly common.

I have the same kind of complaints about Perl's exception handling -- it's entirely possible to hack it into something more useful, but why on Earth should I have to mess around just to make something as fundamental as errors be developer-friendly?

> PHP supports both procedural and OO programming styles -- this is not a bad thing.

Exception handling isn't inherently OO. Perl has its own flavor of try/catch that requires zero objects whatsoever.

> PHP is reference counted with a cycle-detecting GC. That would not leak memory.

I believe it used to, but I removed this due to the short window during which it was a bug. I see this list of counter-arguments hasn't been updated in a while.

> This is true, but it's an ongoing discussion on how to correctly handle scalar type hints. For all the discussion about how PHP isn't designed the author takes issue with the thing they're taking their time on.

My issue isn't that they're taking their time, but that they implement half of a feature and then decide to sit down and think about the other half (while now constrained by whatever hack job they've already done).

> Because of the dynamic abilities of PHP, there is simply no way for the interpreter to ever figure out the variable to close over.

Every other dynamic language ever sure seems to be able to get this right.

> C++ does it. $obj::foo doesn't make any sense, if you're accessing class attributes then you use the class name Class::foo.

Then why not use Class->foo? Why does this need two operators? $obj::foo is perfectly reasonable if I want the foo attribute of whatever class $obj is; that's half the reason I ever use class attributes.

> This is personal taste not a valid critique.

Yes, which is why I said it's personal taste. Regardless, it's still wildly inconsistent with the rest of the language and poorly bolted on.

> That is, in fact, the point. PHP is supposed to be a thin scripting language layer over C. It's expanded beyond that. Many of the poor naming conventions are not because of PHP but rather are the exact API of the underlying C library.

How many people using PHP today came from C, exactly?

> Both the C API and PHP have both these functions for backwards compatibility reasons.

No. The C API has two functions because one takes only a value to escape, and the other takes both a value and a connection pointer. Both functions in PHP can be called with merely a value, and the "real" one will use the current global connection. Zend could have merely switched the old escape function to have the new behavior, and all existing code would have been instantly fixed, not broken.

> Most of these are provided by frameworks just as they are in Python, Ruby, C#, etc.

PHP is praised for its web features, but is missing a whole pile of functionality instrumental for actually writing nontrivial web applications. Either judge PHP only by the core language, or judge everything else by what you get with frameworks.


The real point here is that you're not a PHP programmer. You're complaining about a language you don't use and trolled the web for this material without even testing much of it out yourself.

And sadly your uninformed opinion is now the go-to article when talking about PHP flaws. You've won the Internet.


I drooled far more PHP into my terminal that weekend than you would believe. There were a scant few legitimate errors, and I've removed all the ones brought to my attention.

The rest of it should be factually correct, in which case, why do you care that I listed it? If you're correct in that many of the things I listed aren't really a big deal, the reader will agree with you anyway, right?

(Also, "trawled". No snark intended; it's a neat word and deserves more exposure.)


> If you're correct in that many of the things I listed aren't really a big deal, the reader will agree with you anyway, right?

Because you're supposedly educating non-PHP coders about PHP. Most PHP coders do, in fact, agree with me.


The arguments I've read supporting PHP scare me a little. They seem to boil down to a few things:

* It's not so bad, really. Here's a map of land mines to avoid. Hopefully it's complete!

* PHP is everywhere. Apparently COBOL and Visual Basic were also excellent languages.

* PHP is easy to start with. Newbies don't want to learn anything too hard; they just want to throw down some code. What could possibly go wrong?

* PHP is easy to deploy, as if that's an inherent property of PHP and not something that can be fixed for other languages.

I'd love to hear a real argument for why PHP is a great language for Web development. Not just a defense of PHP. We get it: every language has quirks. I code in C++, willingly even. I know a thing or two about whacky language quirks outside of PHP. But why should I choose PHP over all of my other options?

What makes PHP so great?


> PHP is easy to deploy, as if that's an inherent property of PHP and not something that can be fixed for other languages.

Other languages can fix that (they haven't yet) but at the same time PHP is fixing it's problems at a rapid pace. It seems that PHP is making more progress fixing it's problems and including modern features than other languages are improving their deployment situation.

One advantage of PHP, in my opinion, is that it supports multiple levels of commitment. I recently created a static website for my business; I didn't want the hassle of using a CMS or Wordpress. But I used PHP to include the common headers and footers and handle my contact form. In any other web platform (including PHP with a framework) is terrible overkill for a job like that. But if I want to do something more significant in the future, I can.

PHP's work cycle is also great; if done right you should have no build step. Just edit and hit refresh. I'm currently doing ASP.NET and it's just not possible to iterate as fast during development.

But honestly, I've used a lot of different platforms and PHP just isn't that different. Why choose PHP over all your other options? If your goal is distribution of your app then you can't go wrong with PHP because it's installed everywhere. And, depending on your language experience, you might be more comfortable in PHP because it's very literal; there's no monkey patching or heavy use of dynamic features. But really, there's no reason not use Ruby or Python over PHP.


> It IS a good thing, but it stands out when most of the language is extremely weakly-typed

You only need distinct operators if your language is weakly typed. If you language is strongly typed like Python, Java, or C# then there is never any conflict between addition and concatenation. VB/VB.NET is also weakly typed and has separate operators.

> So some things (objects) are passed by reference implicitly, and some (all else) are not. Yikes!

Yes, like most ever other language in existence. You know, Java, C#, Python, etc.

> Okay. Why not at top-level?

Because all code should be contained within a namespace going forward. Constants should not be defined in the top-level.

> if I write a function that can take either one value or an array of items, and you pass in a single object, I'll get a useless keyed array of its attributes.

No, it doesn't work that way. You have to explicitly cast. If you use an array type-hint you can only pass an array.

> Python and Perl are bytecode-interpreted (not positive about Ruby) and they both have rich module systems that don't require any fussing around.

PHP is also bytecode-interpreted. I'm not really sure what point you're trying to make. It's super easy to integrate code from different libraries with namespaces and autoloading.

> Why does it need to look like a function when it clearly isn't one? return and echo don't.

Because it's used an expression not a statement like return and echo. The fact that is or is not a function is insignificant; you use it the same way.

> In theory, but I've never seen any actual PHP code that uses them.

In templates you see it all the time.

> That's what exception handling is for -- unfortunately, PHP errors are an entirely separate beast from PHP exceptions.

If you convert all errors to exceptions, you could catch it. It's just an additional feature. If you handle your own errors, you can even ignore the error suppression operator if you choose.

> I said "PHP errors don't provide stack traces", and you aren't disputing that... but the runtime doesn't do it for you.

Oh, you're saying if you don't provide any of your own error handling and let it spill out the terminal -- yes, you're right -- no stack trace by default. Not that you should be doing that. If you really want that though, it can be provided by the XDebug extension.

> it's clearly not for compatibility with just PHP4

The lack of E_STRICT helps you run PHP4 code on PHP5. That's why it's not included in E_ALL. For example, I have an application that runs unmodified on PHP4 and PHP5.

> Yet I can't be sure on what parts of the language actually ARE deprecated without reading the entire manual looking for mentions of E_STRICT.

Turn on E_STRICT and it'll tell you.

> A bogus object attribute gets a warning, but a bogus class attribute is a fatal error.

Yes, one is defined and one is not.

> A string value stored in a variable can be called, but the same string value as a literal cannot.

Calling a string literal is pointless! 'test'() is test()!

> Neat, though my understanding is that this still doesn't work with fatal errors, which are shockingly common.

Fatal errors are not that common but I won't argue the point too heavily because they are a bitch. PHP developers are trying to reduce the number of fatal errors. Most IDE's will notify you of fatal error as you type.

> but that they implement half of a feature and then decide to sit down and think about the other half (while now constrained by whatever hack job they've already done).

There's nothing controversial or difficult about object type hinting. Also since PHP is meant to be typeless there is some discussion over whether scalar type hints are even necessary. Giving you something you can use right now is not a bad thing.

> Then why not use Class->foo? Why does this need two operators?

I suspect historical reasons. They really did do very different things in PHP3/PHP4.

> Regardless, it's still wildly inconsistent with the rest of the language and poorly bolted on.

How so? It's PHP object system, there is nothing for it to be inconsistent with in the rest of the language.

> How many people using PHP today came from C, exactly?

It's not about whether they came from C -- it's the fact that PHP quickly implemented access to a huge library of existing C libraries (and tracked their changes). This was a huge deal back when PHP was younger.

> Zend could have merely switched the old escape function to have the new behavior, and all existing code would have been instantly fixed, not broken.

If you've ever complained about security in PHP, you need to give that up right now. Because you just gave everyone a false sense of security.

> Either judge PHP only by the core language, or judge everything else by what you get with frameworks.

Wait, why? That's ridiculous.


tl;dr: I value consistency in my tools because it's a great measure of how frequently they'll trip me up and get in my way while reading or writing code. My biggest problem with PHP above all else, which I tried to write my article around, is that it's an inconsistent jumble from top to bottom.

You're absolutely correct, of course, in that you can write decent PHP by avoiding large chunks of the language, memorizing what things act differently from other things that look the same, not trying to do anything too dynamic, adding boilerplate to every project to fix useless default interpreter behavior, and so on. You can also waltz across a minefield if you just remember where all the mines are. But the necessity of doing all these things is exactly my argument: why bother with all this from a tool that's supposed to help you get stuff done? Because it has $_GET out of the box? You can't even claim "ease of learning" as an advantage after all this, because judging by your own responses, much of the language is pitfalls just waiting to trip up beginners who haven't yet learned the right painful lessons.

Yes, I'm not a PHP programmer. And as a not-PHP programmer, a lot of PHP looks totally crazy. But when outsiders complain about craziness in Python or Perl or Haskell or whatever, at least that craziness can usually be explained as consistent with the rest of the language, or part of an overall philosophy, or the result of some valuable tradeoff. And if not, we're very sympathetic about the ugly warts on our dearly beloved. Yet all anyone has ever been able to tell me about PHP craziness is "well, you shouldn't do that anyway" or "that's how it is in one of ten other languages" or "I have no explanation but here's a workaround so it's like the problem doesn't actually exist, right".

It is hard for me to understand how even someone who loves PHP can't see this as deeply alarming.

> You only need distinct operators if your language is weakly typed.

I don't dispute that: I claim that having separate addition and concatenation operators, but having a single set of equality/comparison operators, is inconsistent.

> Yes, like most ever other language in existence. You know, Java, C#, Python, etc.

Incorrect. Python passes everything by reference (value reference, not name reference) because everything is an object. Passing never performs a copy. I'm under the impression that Java is the same. Perl passes by alias, though the aliases are generally then copied to locals, and it has that whole array-flattening behavior which muddies things.

> Because all code should be contained within a namespace going forward. Constants should not be defined in the top-level.

Everything in Perl is in the `main` namespace unless otherwise specified. One wonders why PHP could not retrofit its new features onto the language like Perl has done for decades, rather than leaving half the language to flounder.

> No, it doesn't work that way. You have to explicitly cast. If you use an array type-hint you can only pass an array.

I'm assuming you're using the explicit cast inside the hypothetical function.

> PHP is also bytecode-interpreted. I'm not really sure what point you're trying to make.

You appeared to be citing interpreted-ness as a reason for having a wonky module system. I am naming other interpreted languages with useful module systems as counterexamples.

> The fact that is or is not a function is insignificant; you use it the same way.

Unless you want to do other function-y things to it, or any of the other pseudo-functions. The syntax is deliberately designed to make you think something is a function, but it only acts like a function in one particular way. (And as a side effect, there are a ton of simple function names you can't use as method names, because the parser gets very confused -- even though this seems like it should be unambiguous.)

> Oh, you're saying if you don't provide any of your own error handling and let it spill out the terminal -- yes, you're right -- no stack trace by default. Not that you should be doing that.

Defaults matter. This is an atrocious default.

> Turn on E_STRICT and it'll tell you.

It'll tell me what things I've already done; I can't easily find out what I should be avoiding proactively.

> Calling a string literal is pointless! 'test'() is test()!

So what? Both are values; why is there any distinction? Hell, you can call methods on numbers in Ruby and Python. I don't care about the practical value here; it's yet another place where PHP is inconsistent for seemingly no reason.

> If you've ever complained about security in PHP, you need to give that up right now. Because you just gave everyone a false sense of security.

Howso? The problem with mysql_escape_string was that it didn't take the current database handle into account. So: make it take the current database handle into account. It may not have solved everyone's problems, but the exceptions are obvious, and it would have fixed problems for far more people than the actual solution (zero).

If you're using multiple handles and passing them around explicitly, you'll have to fix your code either way.


> I'm under the impression that Java is the same.

No, Java is not the same. Scalars not objects in Java and are passed by value. C# is similar, except scalars are value-type objects and are passed by value.

> I'm assuming you're using the explicit cast inside the hypothetical function.

That's not what we were talking about. It's incredibly hard to have a reasonable conversation about this with you because you clearly only know a very small set of similar languages and have no experience with PHP at all.

> You appeared to be citing interpreted-ness as a reason for having a wonky module system.

You cited byte-code interpreted as if that's somewhat significant. PHP's module system really isn't very "wonky" -- it works as advertised. But since you don't use it, you wouldn't know.

> It'll tell me what things I've already done; I can't easily find out what I should be avoiding proactively.

You could read the manual. If you're new to PHP, you'd probably code strictly from the start.

> So what? Both are values; why is there any distinction?

Most languages make the distinction. Why shouldn't there be? That's really ugly code.

> Hell, you can call methods on numbers in Ruby and Python.

That's fine. It doesn't mean every language should do the same. Most languages, especially those PHP is based on, do not do that. Maybe one day PHP will have that but because it's weakly typed, it's difficult to know even what methods should exist. In PHP, it's perfectly reasonable to say strlen(1). Does that mean every number should have string methods? I'm guessing you never considered that?

> The problem with mysql_escape_string was that it didn't take the current database handle into account.

Yes, because the encoding properties of the current database connection are needed for encoding properly. If have two database connections, then what? It picks the first connection as the default and you encode incorrectly? Or if you had a second connection, do you just break all the existing code? What if the second connection doesn't happen every time? Then you're code is broken only every second Wednesday?

You've got a very singular perspective on things. That's fine. But by critiquing another language without knowing it you're making a lot of assumptions and blowing things way out of proportion.


> No, Java is not the same. Scalars not objects in Java and are passed by value.

How are pass-by-value and pass-by-object distinguishable for immutable values?

> That's not what we were talking about.

Yes it is. You said (array) as a cast is useful because a function can accept either a single value or an array of values, and the (array) cast will produce an array either way. I contend that doing this doesn't really work, because passing a single value that happens to be an object will cause the function to cast it to an array of the object's contents, which will have fascinating but useless results.

> You cited byte-code interpreted as if that's somewhat significant.

I only mentioned bytecode for the sake of pedantry: strictly speaking Python isn't interpreted, whereas e.g. shell is.

> You could read the manual.

I had to do quite a lot of that. It's kind of wordy. :)

> Most languages make the distinction. Why shouldn't there be? That's really ugly code.

I'm not proposing that people write code like this. I'm objecting to the inconsistency between a value in a variable and a value in source code.

Note that, for the same reason, you also can't chain calls like `foo()()`. There ARE good reasons for that: you could return a function name, or a closure, or an object that supports being called. But because the parser doesn't just allow trying to use parentheses on an arbitrary value, this doesn't work. Just like `foo()[]` didn't work until recently, because it too had to be special-cased.

> That's fine. It doesn't mean every language should do the same. Most languages, especially those PHP is based on, do not do that.

Really? C doesn't have methods. C++ has methods, but string literals are C strings so they have no methods. Perl doesn't consider builtin types to be objects, but if you turn them into objects with `autobox`, methods work equally well on variables and literals. Python allows method calls on literals -- and will let you try to call them, but of course literal strings aren't callable so this won't do anything. It parses, though. Ruby is the same. "foo".equals("bar") is a common Java idiom.

What language are you thinking of where there's a distinction made -- in the parser, no less -- between a variable and an expression?

> Maybe one day PHP will have that but because it's weakly typed, it's difficult to know even what methods should exist. In PHP, it's perfectly reasonable to say strlen(1). Does that mean every number should have string methods? I'm guessing you never considered that?

Sure, why not? Not that I was suggesting PHP direly needs scalar methods, but if a number responds to strlen(), why not to ->strlen()?

> Yes, because the encoding properties of the current database connection are needed for encoding properly. If have two database connections, then what?

Then you're screwed no matter what Zend does and still need to fix your code. So the options were: 1. Leave the existing function totally broken. Create a new one with a confusing and even longer name. Make everyone fix their code and remember to use the new function in the future. 2. Fix the issue in-place for the vast majority of existing code. Make the edge cases fix their code by doing the same thing they have to do with every other API function anyway. Optionally, throw a warning when multiple handles exist and mysql_escape_string is called with only one argument.

What, then, is the appeal of (1)?

> You've got a very singular perspective on things. That's fine. But by critiquing another language without knowing it you're making a lot of assumptions and blowing things way out of proportion.

I'm hearing this a lot, but (as far as I can be trusted to say this) I don't see it. I draw a lot of comparisons to Python and Perl because they're in the same family and I know more about their inner workings than anything else. That doesn't mean they're the only languages I've used or the only languages I think are worthwhile.

Yes, I picked on a lot of little things. It's the little things that matter. Every language (ahem, most) has function calls, data structures, and loops. What differentiates them is the little day-to-day stuff.

So what am I missing? What makes these design decisions good, what makes PHP great? I've heard a lot of defenses and a lot of statistics, but not too many outright advantages. Most of your original response is just workarounds, not reasons why the behavior is good or even acceptable. The image I'm left with is that of an overgrown playground filled with active mines, but most of the mines have upturned buckets over them so you probably won't step on them, and that's supposed to make it a great place to send your kids. If even PHP's supporters can do no better than explain how to write passable PHP when I have a gun to my head, why would I want to use it?


> How are pass-by-value and pass-by-object distinguishable for immutable values?

They aren't really. There's no real technical difference, just a terminology difference. All that you need to know is that whether it be Python, PHP, Java, or whatever that passing around scalars and objects works out the same.

> You said (array) as a cast is useful because a function can accept either a single value or an array of values, and the (array) cast will produce an array either way.

I never said anything about functions -- just that the cast itself is useful.

> because passing a single value that happens to be an object will cause the function to cast it to an array of the object's contents, which will have fascinating but useless results.

People cast objects to arrays in PHP all the time because that can be a useful operation. I understand you point, but I don't really think it's too valid. If you're explicitly doing a cast, you should know what you're casting from. This is sound advice no matter what language you're using.

> strictly speaking Python isn't interpreted, whereas e.g. shell is.

It's an implementation detail that's not significant. The next version of bash should byte-code compile everything behind the scenes and run it (like PHP does) and it wouldn't make any difference. You could write an interpreter for C code (they exist) and it wouldn't change anything about C.

> Note that, for the same reason, you also can't chain calls like `foo()()`.

Honestly, there's no language grammar reason why that shouldn't work in PHP. It's just that parser sucks and they're very slow/careful to make changes to the parser. If it's a function name, a closure, or an object that supports being called they're called the same. If you can do $foo() then you should be able to do foo()(). The same is true about foo()[]. These things don't have to special-cased so much as the parser has to be modified to be more generally accepting.

> What language are you thinking of where there's a distinction made -- in the parser, no less -- between a variable and an expression?

PHP makes no distinction between a variable and an expression (except as described above). It's make a distinction between scalars and objects.

> Sure, why not? Not that I was suggesting PHP direly needs scalar methods, but if a number responds to strlen(), why not to ->strlen()?

Then there's really no point in having scalars be objects. You could add syntactic sugar to make strlen($x) and $x->strlen() do exactly the same thing but what would be the point? I'd rather they do something more interesting with that ability. I think it's the only way they can successfully implement unicode.

> Leave the existing function totally broken. Create a new one with a confusing and even longer name. Make everyone fix their code and remember to use the new function in the future.

MySQL made this decision, not PHP. They just give you the library to use. Anyway, you seem to have a problem with the concept of backwards compatibility -- it generally does mean "continue to use this broken thing because you don't want to change your code".

> I'm hearing this a lot, but (as far as I can be trusted to say this) I don't see it.

Someone tells you that you lack perspective and you don't see it -- so ironic! (I'm just being cheeky)

> I draw a lot of comparisons to Python and Perl because they're in the same family and I know more about their inner workings than anything else. That doesn't mean they're the only languages I've used or the only languages I think are worthwhile.

Yes, but going off on public/protected/private as if it's a flaw in PHP because you don't like them is not a valid critique. That's just one example but there are others. Even saying everything should be an object is more personal taste than anything else. I very much like "everything is an object" but it's not clear how best to implement that in PHP yet.

> It's the little things that matter. Every language (ahem, most) has function calls, data structures, and loops. What differentiates them is the little day-to-day stuff.

I disagree. I think I probably switch between languages a bit more than you do and the little things don't matter that much. What matters is the big things. Most of the stuff you mention in your article, if I encounter them at all, I don't even notice. It's such a non-issue that unless you bring it up, I wouldn't think to tell you. In fact, in some cases, I wasn't even sure what you were talking about because I don't encounter them (the lack of stack traces on errors, for example).

> I've heard a lot of defenses and a lot of statistics, but not too many outright advantages.

Indeed. I'm not saying PHP has advantages over other platforms -- it has some -- but, in the end, the differences between any of the platforms aren't significant and mostly personal taste. I continue to code in PHP because I know PHP, I know the frameworks, and I have lots of existing PHP code. If I had to write Python or Ruby, I would. I'm going to be writing ASP.NET code for next 6 months.

I just think your article blows everything out of proportion. Much of it is "look how this crazy unreasonable code reacts in PHP". It's not invalid but it's not really indicative of developing in PHP. Similar lists have been made for JavaScript and yet that doesn't affect opinions too much. Similar lists have been made for C and C++ but everybody knows what they're getting into there.

Here we are talking about mysql_real_escape_string() and that's as legacy as you can get.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: