Skip to content

Instantly share code, notes, and snippets.

@aerosol
Created January 19, 2012 13:48
Show Gist options
  • Select an option

  • Save aerosol/1640124 to your computer and use it in GitHub Desktop.

Select an option

Save aerosol/1640124 to your computer and use it in GitHub Desktop.
+---------------------------------------------------+
| The following takes place between 03:00 and 04:30 |
+---------------------------------------------------+
03:00 * toxik snickers
03:02 < toxik> [in #php]
03:02 < toxik> <@toxik> PHP -- one of few languages where a string can be false
without being empty.
03:02 < toxik> <@toxik> And that's a god damn feature. :-)
03:02 < toxik> < Seph> a string should be neither true nor false, it should be
a damn string unless explicitly converted
03:02 < toxik> <@toxik> Yes, explicit is better than implicit. But practicality
beats purity.
03:12 < tappi> right
03:12 < tappi> what does string being true or false mean
03:12 < toxik> In PHP, if ("0") { ... } will never execute the inside.
03:13 < buster> omg
03:13 < buster> and thats intended?
03:13 < toxik> Yes.
03:13 < buster> lol.
03:13 < tappi> string is a string unless converted, either explicitely or
implicitely :P
03:14 < toxik> However, if (array(0)) { ... } -will- execute, don't ask me.
03:14 < buster> haha.. like testing some inutstringsfrom websites and feiling
if the user entered 0
03:14 < buster> hahahaha
03:14 < buster> *failing
03:15 < toxik> Oh yeah, but they have an operator for that.
03:15 < toxik> if ($x === "0") and you'll know if it _really_ is "0".
03:16 < buster> lol@ ===
03:16 < buster> if( 8===D )
03:16 < buster> <3
03:16 < tappi> :D
03:16 < toxik> That actually works
03:16 < toxik> If you define the constant D first.
03:17 < buster> and thats why php actually stands for penis horsepower
03:18 < toxik> You know what's handy though? You can define a class named D, a
function named D, and a constant named D, and be able to refer
to them the exact same way without having to worry. Anywhere in
your code!
03:18 < toxik> Like so: $D = new D(D(), D);
03:18 < tappi> yes, i so like it when a language allows me to shoot me in my foot
03:18 < buster> omfg
03:19 < buster> no i begin to hate php, toxik, thanks
03:19 < toxik> But I'm not even started!
03:20 < buster> i always thought of it like "oh well, looks creepy, wont use
that.. but it's so widely sed, should have some good things"
03:20 < buster> :F
03:20 < buster> *used
03:20 < buster> i''ve read some articles about how bad php is
03:20 < toxik> Let's move on to one of the larger WTFs -- echo and print.
03:20 < buster> mostly they complain about classes and stuff
03:20 < buster> but thats some basic stuff which is really really sucky
03:21 < toxik> echo, its syntax is simple: echo "foo";
03:21 < toxik> Notice how it's not a function? Well, we can accept that. Python
had the print statement and all. It's relics.
03:21 < toxik> So then. print, simple: print("foo");
03:22 < toxik> So, you might be asking, what does print return? int(0).
03:22 < toxik> Now what on Earth is wrong with that, you ask.
03:22 < toxik> I'll show you.
03:22 < toxik> $ php -r 'var_dump(function_exists("print"));'
03:22 < toxik> bool(false)
03:22 < toxik> print isn't a function.
03:22 < toxik> It has the exact same syntax. It has a return value. But it's not.
03:23 < buster> wtf
03:23 < buster> hey, so you can overwrite print
03:23 < toxik> They could _easily_ replace it with a real function and have the
language be a lot cleaner (as you could use it in callbacks) -- but no.
03:23 < toxik> Oh, no.
03:23 < toxik> God no.
03:23 < toxik> PHP's parser treats print and echo like their own tokens--
because they're so-called language constructs.
03:24 < toxik> If you try to do function print() {}, you'll get a parse error.
03:24 < toxik> After all, why would you be trying to print in the middle of a
function definition?
03:24 < buster> hahaha
03:24 < buster> those are really scary things
03:25 < toxik> So yeah, that's some of the finer parts of PHP.
03:25 < buster> and that they didnt "fix" this stuff in all those years..
somehow.. i think php doesnt come forward :F
03:25 < toxik> Oh no no no, don't think that. PHP is evolving! Into Java.
03:25 < toxik> PHP has type hinting. Really. You can do:
function foo(TheClass $foo) { ... }
03:26 < buster> :o
03:26 < toxik> However, you can't really do that with array, string, int, or
any other basic type. Because they're that: types, their own
tokens. So why would you be declaring an array or a string
before an argument, the parser asks.
03:26 < buster> hahahaha
03:26 < buster> ROFL
03:26 < buster> thats awesome
03:27 < buster> can't be true
03:27 < buster> lies!
03:27 < toxik> PHP /is/ awesome.
03:27 < buster> roflrofl
03:27 < toxik> Want to hear about PHP references?
03:27 < toxik> Because those are a great story, too.
03:27 < buster> also, wasn't there some discussion abotu some new operator? and
they chose like the shittiest character available? :o
03:27 < toxik> Oh yeah, but I'll save that for later.
03:27 < buster> <3
03:28 < toxik> References first. They're funny business.
03:28 < buster> toxiks bedtimestories
03:28 < toxik> :>
03:28 < toxik> I'm preparing examples for this one, 2 ticks.
03:28 < buster> ye
03:30 < toxik> <?php
function my_fun1($x) { $x[] = "foo"; }
function my_fun2(&$x) { $x[] = "bar"; }
// Note how the array "type" has its own unique syntax. <3
$innocent_array = array(hello => "world");
my_fun1($innocent_array); var_dump($innocent_array);
/* array(1) {
["hello"]=>
string(5) "world"
} */
my_fun2($innocent_array); var_dump($innocent_array);
/* array(2) {
["hello"]=>
string(5) "world"
[0]=>
string(3) "bar"
} */
?>
03:30 < toxik> PHP is programming with potentially hidden side-effects.
03:30 < toxik> Note my_fun2, the argument has been declared as "a reference".
03:31 < buster> i see
03:31 < toxik> Note how my_fun2 can mutilate the array in any way it likes,
without the code at line 22 knowing about it.
03:31 < toxik> Now, this is what we're used to in Python.
03:31 < toxik> Because we _always_ pass by reference.
03:32 < toxik> However, in PHP, this isn't common at all. In fact, I'm fairly
sure they've deprecated it.
03:32 < toxik> That, or the other way around -- see PHP can also force a
function to take a reference.
03:32 < toxik> Consider my_fun1(&$innocent_array);, its effect is that of line 22.
03:32 < buster> ye
03:33 < toxik> Now, I know, you're thinking: this isn't much of a WTF.
03:33 < buster> actually
03:33 < toxik> But I'm not done. Because this has to do with their "OOP".
03:33 < buster> i dont get why fun1 doesnt do shit to the array
03:33 < buster> :p
03:33 < toxik> Oh, PHP copies the entire memory area.
03:33 < buster> ahhh, ok, i get it
03:33 < buster> it writes into the copy
03:33 < buster> yeyeye
03:34 < toxik> (Actually I recall ekneuss telling me how smart they've made PHP
about that, it only copies if you modify it, so in our example,
it should.)
03:34 < toxik> But before I go into OOP, think about that for a second.
03:34 < buster> not used to that anymore
03:34 < toxik> PHP copies every value passed if you modify it.
03:34 < toxik> Can you even imagine the performance wreakage if you pass
marginally large datasets?
03:34 < buster> ye
03:35 < toxik> Allocate, copy, free, repeat.
03:35 < toxik> Insanity.
03:35 < toxik> Anyway.
03:35 < toxik> So, as you might've noticed, PHP's built with pass-by-value,
just like VB6. Though not a very wise choice, they made it.
03:35 < tappi> lol :P
03:35 < toxik> Now ponder that for two seconds.
03:35 < toxik> What does that mean if you pass objects?
03:36 < buster> wait
03:36 < buster> i bet objects/classes are passed by refernce always
03:36 < buster> :p
03:36 < buster> no?
03:36 < toxik> Let's go back a few years to PHP 4, when OOP was introduced.
03:36 < toxik> "For real"
03:36 < buster> :>
03:36 < toxik> Let me give you an example of the generic PHP OOP.
03:37 < toxik> class Klass { ... }
// Important to note: THIS IS NOT &=. That means "binary and".
// This is "Set to reference of".
$my_obj =& new Klass();
fun($my_obj);
03:38 < toxik> Now that's already a WTF in itself and I don't see how they
couldn't see that themselves, but anyway.
03:38 < buster> :o
03:38 < toxik> Note how $my_obj now is a... reference variable? What?
03:38 < buster> so my obj is the pointer to a new klass
03:39 < toxik> No no, line 9 there is the PHP equivalent of "my_obj = Klass()"
03:39 < toxik> So, if you missed doing =& instead of =, you'd be having your
object copied _all over the place_, like really.
03:40 < toxik> Or, alternatively, if you typed &=, you'd be doing binary and
between an uninitialized variable and a new object. Meaningful?
No. Did it stop scripts? No. Because that's non-fatal in PHP.
03:40 < buster> hha :>
03:40 < toxik> (That, by the way, is another _major_ WTF in PHP. Error handling.)
03:40 < buster> thats all so retarded stuff :>
03:40 < toxik> Forward to PHP 5, current stable.
03:41 < toxik> Same example, only now $my_obj = new Klass(); will suffice, for
$my_obj will become a reference anyway. Is that consistent? No.
Is that expected? No.
03:41 < toxik> At least they stopped reallocating memory all over the place.
03:42 < buster> i see
03:42 < buster> lol :>
03:42 < buster> ?? php
03:42 < buster> :>
03:42 < toxik> So that's how PHP's implicit reference variables came to be, and
I hope you'll understand when you read PHP code that makes no
logical sense.
03:43 < toxik> And now, let's discuss pseudo-variables.
03:43 < buster> :o
03:43 < toxik> PHP has this very, very awkward way of dynamically looking up
variable names.
03:43 < toxik> If you do $x = "a"; $z = "x"; echo $$z; you'll get "a".
03:43 < buster> actually i started with php and webprogramming, like everyone
else i guess.. bu ti don't remember much of it
03:44 < buster> what?
03:44 < buster> whats $$?
03:44 < buster> oic
03:44 < toxik> Further, if you also did $a = "z"; you could do:
$$$$$$$$$$$$$$$$$$$$$$$$$$$z
03:44 < buster> the variable with the name of the content of the second one...
if it would be like that :p
03:44 < toxik> $ php -r '$x = "a"; $z = "x"; $a = "z"; echo $$$$$$$$$$$$$$$$z;'
03:44 < toxik> x
03:45 < toxik> Now, you might feel it's a little bit over the top to implement
a language feature just to do this (locals() anyone?) but the
PHP team made
their decision.
03:45 < toxik> So, as fate has it, this often turns out to be moderately useful
in templating engines.
03:46 < toxik> Now, quick reminder of PHP OOP:
class X { function meth() { echo $this->blah; } }
03:46 < buster> aye
03:46 < toxik> Fair enough, you say.
03:46 < toxik> Well, what if I were to make it:
function meth() { $x = "this"; echo $$x->blah; }
03:46 < toxik> Would it work?
03:46 < toxik> No.
03:47 < toxik> Why? Guess why.
03:47 < buster> wtf
03:47 < buster> dunno :<
03:47 < toxik> Come on, I dare you.
03:48 < toxik> Take a moment, and brace yourself: $this is not a variable.
03:48 < buster> because.. String has no bla
03:48 < buster> :F
03:48 < toxik> $this. is. not. a. fucking. variable.
03:48 < toxik> It's _pseudo-variable_.
03:49 < buster> oh, so $this is just another hacked in stuff thing
03:49 < toxik> Exactly.
03:49 < buster> nice :)
03:49 < toxik> I'm not even going to discuss PHP's upcasting mechanism (super).
03:49 < toxik> It's... Impolitely weird.
03:50 < toxik> So, where were we. Oh right, the funny operator.
03:50 < buster> do you think this should work? all the $$x crap? its scary
03:50 < toxik> Oh but it does work.
03:50 < buster> yeah, the namespace separator. i remembered :p
03:50 < toxik> But not with this.
03:50 < buster> well.. dunno.. it just cries for bugs and exploitable code i guess
03:51 < toxik> Well yeah, but it's PHP. Come on. It has register_globals.
03:52 < buster> wanst that some scary stuff that is highly recommended to be
turned off? :p
03:52 < buster> i remember years ago when every fucking php software brocke
when you followed the recommendation
03:52 < toxik> Yeah, it was a very, very bad idea from the start.
03:53 < toxik> But let me show you one fun example of pseudo-variable $this.
03:53 < buster> :)
03:53 < toxik> class K { function m() { $x = "this"; var_dump($$x); } }
new K(); -- doesn't work, right. I showed you before.
03:54 < toxik> (It works though, just prints NULL. See, referencing inexistant
variables is non-fatal, but you know that.)
03:54 < buster> i see
03:54 < toxik> Now... The version that does work:
class K { function k() { $z = $this; $x = "z"; var_dump($$x); } }
03:55 < toxik> If you just assign $this to another variable, you can reference
that instead.
03:55 < toxik> Weird? Yes.
03:55 < buster> lol
03:55 < buster> yes get it
03:55 < buster> hah
03:55 < toxik> So maybe you're thinking, "What, but just do $this = $this;"
03:55 < toxik> But NO! FATAL ERROR!
03:55 < toxik> Fatal error: Cannot re-assign $this in /home/toxik/- on line 4
03:56 < buster> wtf
03:56 < buster> mh
03:56 < toxik> So, get this: in order to get $$x to work in my example, you
have to call an outside plain function and pass it $this as an
argument.
03:56 < toxik> YAY OOP!
03:57 < buster> :>
03:57 < toxik> And another piece of brokeness.
03:58 < toxik> Suppose you have object $car with attribute "color",
$car->color, right.
03:58 < buster> yep
03:58 < toxik> With the dynamic reference thing, you could do,
$x = "color"; echo $car->$x; -- not that weird, expected in a way.
03:59 < toxik> If you had a class Car with class constant numWheels, you could do
Car::numWheels, right.
03:59 < buster> i find it creepy
03:59 < buster> ye
03:59 < toxik> BUT! You couldn't do the equivalent: $x = "numWheels"; echo Car::$x;
03:59 < toxik> Because you just fucking can't.
03:59 < buster> rofl
04:00 < buster> i like that, php sounds like an adventure, everytimeyou think
you get it, another thing comes up, you'll never stop learning
and advancing
04:00 < buster> like a labyrinth
04:00 < toxik> Yeah.
04:01 < toxik> I think it's their strategy: make it so convoluted that once you
learn, everything else gets too easy to remember.
04:01 < toxik> You need the challenge, dammit!
04:01 < buster> haha, yes
04:01 < toxik> Fuck binary trees and any interesting topic, the language should
pose the bigger challenge!
04:01 < buster> also, can you have numWheels as variable and function?
04:01 < toxik> Of /course/
04:01 < toxik> (Actually need to double-check that one.)
04:02 < buster> so i suppose php doesnt have the python thingy variable()
04:02 < buster> you know.. dunno whats it called to call a method "in a variable"
04:02 < buster> :p
04:02 < toxik> Ah, yeah. You can.
04:02 < toxik> Day is saved.
04:02 < buster> and what does it call then? :o
04:03 < buster> the variable or the method?
04:03 < toxik> I meant this:
class K {
var $m = "HI!";
function m() { echo $this->m; }
}
$t = new K(); $t->m();
04:03 < buster> sounds like fun!
04:03 < toxik> Prints "HI!"
04:03 < toxik> But buster, sigh. You can't reference methods or functions like that.
04:04 < toxik> If you mean to do the function call equivalent of dynamic
variable thingy, you do it using strings for functions.
04:04 < toxik> Like so: function x() { ... } $k = "x"; $k();
04:04 < buster> yeah
04:04 < toxik> The reason is that in PHP, functions are part of a global
registry consisting only of their name.
04:05 < toxik> Just like in C: flat namespace.
04:05 < buster> yes
04:05 < toxik> Only in C you can actually get addresses of functions and that.
04:05 < toxik> So PHP's actually more inflexible on that front, but eh.
04:05 < toxik> Hard to beat a new-thinking language like C.
04:05 < toxik> I suppose.
04:06 < buster> haha
04:06 < toxik> Anyhow, so. buster, guess how you'd do the $k() thing for
methods on instances!
04:07 < buster> $k = "instance->x"; ?
04:07 < toxik> Nope. Sorry.
04:07 < toxik> It's... *tension rises* ... $k = array($instance, "meth"); $k();
04:08 < buster> that doesnt make the slightest sense
04:08 < buster> like
04:08 < toxik> Nope!
04:08 < buster> not at all
04:08 < buster> wtf =D
04:09 < toxik> At least you can call static methods with:
$k = array("Klass", "smeth"); $k();
04:09 < buster> acually i can imagine how many people use this stuff because
they think it's some advanced optimized php stuff and to show
their mad skills
04:09 < buster> creepy
04:09 < toxik> I used to.
04:09 < buster> omg
04:10 < buster> i'd kill you if i were to read sour sources
04:10 < toxik> But uno mas.
04:10 < buster> *your
04:10 < toxik> You know of Python's f(*args), right?
04:10 < buster> ye
04:10 < toxik> Try the equivalent in PHP.
04:11 < buster> i bet * isn't allowed because it multiplies stuff
04:11 < buster> :>
04:11 < toxik> I understand if you had no idea how to do it.
04:11 < toxik> The answer is, ironically, a function this time.
04:11 < toxik> call_user_func_array("f", $args);
04:11 < buster> hu?
04:12 < toxik> Were you to do it on a method, you'd have a pretty nice long
line right there.
04:12 < buster> call_user_.... is a builtin or what?
04:12 < toxik> Yup.
04:12 < toxik> http://se.php.net/call_user_func_array
04:12 < buster> haha
04:12 < buster> amazing
04:12 < toxik> Its other cousin, call_user_func, is less useful.
04:12 < toxik> It actually has no use at all.
04:12 < toxik> All it does is $k($x1, $xN...);
04:13 < buster> how can one come up with thi sshit if one designs a language? i
mean.. it has been solved in every language before
04:13 < toxik> The name I have no idea they chose. Something like "call" and
"call_args" would've been fine, but no.
04:14 < toxik> And as I said, call_user_func($callback, ...) is a mimic of
$callback(...).
04:14 < toxik> Only it's even worse.
04:14 < buster> hehehe
04:14 < toxik> If you read the manual you'll note that you can't use our
beloved references with call_user_func.
04:14 < buster> lol
04:14 < toxik> For that, they recommend call_user_func_array($callback, array(&$arg));
04:14 < buster> you youll copy everything with it
04:14 < buster> :>
04:14 < toxik> And yes-- array indices can actually be references!
04:15 < toxik> Now let's discuss lambdas.
04:15 < toxik> Just briefly.
04:16 < toxik> Lambdas have their issues.
04:16 < toxik> But PHP's implementation is just... dirty.
04:16 < toxik> Classically it's known as create_function().
04:16 < toxik> It returns "a callback"
04:16 < toxik> Which is actually a string of random letters assigned as a name
for a generated function.
04:16 < toxik> So all they do is make a new function with a random name.
04:17 < toxik> Not very anonymous at all, you'd argue.
04:17 < buster> yes
04:17 < toxik> And I can't counter that.
04:17 < buster> :p
04:17 < buster> actually i have headaches like hell
04:17 < buster> but that cheered me up
04:17 < buster> \o/
04:18 < buster> nerdtalk
04:18 < toxik> \o/
04:18 < toxik> (Now please post log kthx.)
04:19 < toxik> There are actually many more things in PHP which I could rant
about, like the terribly broken error reporting or the
namespaces, but I really need to sleep. :<
04:19 < buster> have to get it from lurky i guess, one moment
04:20 < toxik> One of the fundamentally broken things I've been angry about is
the type hinting too.
04:21 < toxik> You know, they took the idea from Java and the likes. Only they
neglected one fine detail: Java is a strongly typed fucking
language. In Java, types matter. In PHP, "0" is false.
04:23 < toxik> An elementary usecase: In Java, you could say "I expect a
collection of integers in this argument."
04:23 < toxik> In PHP, you don't have that typing. At best (but you can't
because of previously mentioned parsing issues), you'd be able
to say "I want an array."
04:23 < toxik> At which point you lost the whole point in type hinting.
04:24 < toxik> How could they not see that this is funda-fucking-mentally broken?
That concludes the rant, but it doesn't exhaustively list everything that's
wrong with PHP. Far from it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment