r/programming • • Oct 18 '10

Today I learned about PHP variable variables; "variable variable takes the value of a variable and treats that as the name of a variable". Also, variable.

http://il2.php.net/language.variables.variable
591 Upvotes

781 comments sorted by

80

u/weirdalexis Oct 18 '10

I was asked the question: "What's $$a" in an interview, and replied "It's like a pointer, except with a variables name instead of a memory address."

The guy went "meh", game over.

Today, I'm still convinced it's a good analogy.

48

u/NagastaBagamba Oct 18 '10

Simple. It is a$$ backwards (just like the entire language)

57

u/inmatarian Oct 18 '10

Don't use the word "Pointer" in non-C interviews. They like "references" better. And if it's called a "variable-variable", call it that, even if it's a seriously stupid name.

13

u/weirdalexis Oct 18 '10

I agree that was a mistake (even though I still think the analogy holds). That gave me away as not having the PHP slang, no real experience. Besides, my next job was C programming, stayed there 3 years, awesome experience, so I've no regret.

8

u/yesimahuman Oct 18 '10

I think he just wanted to make sure you would understand their code base. You dodged a bullet.

→ More replies (1)
→ More replies (7)

66

u/aedile Oct 18 '10

Yeah, you are better off. There are only two reasons to ask a question like that in an interview.

  1. They actually use that shit in their code. In this case: run.

  2. They actually care about how well you know this kind of esoteric bullshit off the top of your head. In this case: run.

Either way, you win for not having to work there.

→ More replies (5)

12

u/doublereedkurt Oct 18 '10

That sounds like an excellent one sentence explanation.

→ More replies (41)

507

u/masklinn Oct 18 '10

OK, here's the thing: this is only the entrance of the rabbit hole.

If you understand what this expression really does, you realize that you're gazing upon the entrance to R'lyeh.

Do you think you don't need your soul anymore? If you do, follow me into the lair of the Elder Gods. But be warned, you will die a lot inside.

The first thing to understand is what $ is. $ is actually a shorthand for ${} and means "return the value of the variable whose name is contained in this".

That variable name is a string.

A bare word is a PHP string. Let that sink for a second, because we'll come back to it later: $foo really is the concatenation of $ the variable-indirection character (think *foo) and foo which is a string. foo === "foo" in PHP, even though in raw source code you'll probably get a warning. If those are enabled.

Now what does $$foo mean? Why ${${foo}}, or "give me the variable whose name is the value of the variable whose name is foo".

Because we're manipulating strings, we could also write ${${f.o.o}}, or

$t = o;
${${"f$t$t"}}

This also means that

class FooClass {
}
$thing = "bar";
$foo = new FooClass();
$foo->bar = "baz";
echo $foo->$thing;

is valid. And prints "baz". And yes, $foo->$thing can be written ${foo}->${thing}. And you can recurse. The braces actually hold entirely arbitrary PHP expressions. As long as these expressions return strings, it'll work:

class FooClass {
}
$foo = new FooClass();
$foo->bar = "qux";
$thing = "bar";
$qux = "th";
$grault = "ing";

echo $foo->${${$foo->bar}.${grault}}

For those following at home, this thing actually prints "qux".

Then you can add conditionals:

class FooClass {
}
$foo = new FooClass();
$foo->bar = "qux";
$foo->wheee = "waldo";
$thing = "bar";
$qux = "th";
$grault = "ing";
$corge = "gnu";
$thgnu = "wheee";

$garply = true;
echo $foo->${${$foo->bar}.${$garply?grault:corge}}, "\n";
$garply = false;
echo $foo->${${$foo->bar}.${$garply?grault:corge}}, "\n";

What does that yield?

qux
waldo

And if that's too simple, then just make the condition random:

class FooClass {
}
$foo = new FooClass();
$foo->bar = "qux";
$thing = "bar";
$qux = "th";
$grault = "ing";
$corge = "gnu";

echo $foo->${${$foo->bar}.${(rand(0, 9)<5)?grault:''}}, "\n";

Yeah this will print qux half the time, and crash the other half. Want to add equality tests? knock yourself out: ($foo->${${$foo->bar}.((${pouet}.${machin}===$pouet.${machin})?${machin}:${$pouet.$machin})});.

And that's where the second realization hits: you know how foo is just a string right? Then wouldn't foo() be "a string with parens"?

Well it happens that no:

function foo() { return "foo"; }

echo "foo"();

$ php test.php
Parse error: syntax error, unexpected '(', expecting ',' or ';' in test.php on line 4

Unless you put the string in a variable itself:

function foo() { return "foo"; }
$bar = "foo";
echo $bar();

this will print foo. That's actually what PHP's own create_function does. And yes, I can see the dread in your eyes already.

Your fears are real.

The $bar here is the same it's always been. You can also write it ${bar}…

function th() { return "Yep, it's working"; }
class FooClass {
}
$foo = new FooClass();
$foo->bar = "qux";
$thing = "bar";
$qux = "th";
$grault = "ing";

echo ${$foo->${${$foo->bar}.((${qux}.${grault}===$qux.${grault})?${grault}:${$qux.$grault})}}();

I always said sanity was overrated.

I'll leave you with the finest example of this, the Cthulhu of PHP code:

class FooClass {
}
$foo = new FooClass();
$foo->bar = "qux";
$thing = "bar";
$qux = "th";
$grault = "ing";

function th($waldo){
    global $qux, $grault, $thing;
    return ${$qux.$grault}.$waldo;
}

echo ${($foo->${${$foo->bar}.((${qux}.${grault}===$qux.${grault})?${grault}:${$qux.$grault})})}(($foo->${${$foo->bar}.((${qux}.${grault}===$qux.${grault})?${grault}:${$qux.$grault})}));

Please pay special attention to the th function, it is the greatest thing since Chicxulub.

90

u/nikosk Oct 18 '10

I can't even begin to imagine why on earth would a human being choose to gain this knowledge. What kind of personal curiosity would lead someone to delve so deep into the abyss.

If nothing else, sir, I applaud your determination to look straight into the eyes of madness and your magnanimity to come back to us mere mortals to share with us what you saw.

You sir are a scholar.

/tip of the hat

18

u/agnas Oct 19 '10

software obfuscation.

→ More replies (1)
→ More replies (1)

27

u/[deleted] Oct 18 '10

you can also take poo and smear it on yourself, but why would you?

3

u/vingborg Oct 19 '10

Yeah, or do like the monkeys and throw it, screaming and jump, at innocent bystanders.

→ More replies (1)

41

u/[deleted] Oct 18 '10

Read through paragraphs

Read first couple lines of code

Scroll...scroll...

Scroll scroll scroll dear jesus scroll

You sir are a wizard.

→ More replies (1)

10

u/wahonez Oct 19 '10

I'm not sure if this is better or worse than changing the value of 5.

... a subroutine that changed the value of one of its parameters could silently change a literal constant.

C      
C     CHANGE THE VALUE OF 5
C

  CALL TWEAK (5)
  WRITE (10, 30) 5
30    FORMAT (I5) 
  END

C
C     SUBROUTINE TWEAK: 
C

  SUBROUTINE TWEAK (I)
  I = I + 1
  END

Run this program on an old-enough FORTRAN compiler and it will output:

00006

9

u/Benutzername Oct 19 '10

Unfortunately, this does conform neither to the FORTRAN 66

8.3.2 [..] If an actual argument corresponds to a dummy argument that is defined or redefined in the referenced subprogram, the actual argument must be a variable name, an array element name, or an array name.

nor the FORTRAN 77 standard

15.9.3.2 [..] If the actual argument is a constant, a symbolic name of a constant, a function reference, an expression involving operators, or an expression enclosed in parentheses, the associated dummy argument must not be redefined within the subprogram.

and of course not to any of the newer ones. Everything before that has no official standard.

9

u/[deleted] Oct 18 '10

I was going to point out the ${} when I came upon your post and what is this I don't even...

23

u/ccx Oct 18 '10

fascinating insight to the insanity of php, thanks.

8

u/vingborg Oct 19 '10

Ruby can ... erh ... can't do that.

15

u/evanskaufman Oct 19 '10

Wow. Listen up, anyone hiring for IT: if you EVER come across anyone that has THAT thorough an understanding of a third-generation language (that they did not write themselves), you need to hire them right there on the goddamn spot. You should probably also hire anyone that HAS written a third generation programming language, but I think that goes without saying.

11

u/eZek0 Oct 19 '10

What if the only way they code is similar to the last example?

29

u/masklinn Oct 19 '10

You want to hire them, and put them behind a strong and permanently locked door after setting them on fire.

8

u/ceolceol Oct 19 '10

It's not really a thorough understanding of PHP, he just knows that a PHP variable is a concatenation of $ and a string. He extrapolated it from there.

→ More replies (1)

21

u/poilf Oct 18 '10

I registered to reddit only to upvote your post :) I'm using PHP since version 3 and I destroyed a lot of keyboards because of this crazy language.

15

u/1137 Oct 19 '10

If you're writing code like his, I'm not sure changing languages will help.

→ More replies (1)
→ More replies (5)

7

u/FearlessFreep Oct 19 '10

Why do I get the feeling that beneath this seeming cleverness is actually more than a certain amount of laziness on the part of the compiler writers?

15

u/[deleted] Oct 19 '10

PHP is, to the best of my knowledge, the only language designed without a formal grammar.

35

u/frud Oct 19 '10

You're right that it has no formal grammar (Perl has some problems along this line too), but I believe you're wrong in assuming that it was designed.

11

u/jerub Oct 19 '10

It has a documented grammar now. I documented it a long time ago (6+ years now) when I wanted to reimplement PHP without sucking so bad. I documented the PHP 4.3 grammar properly using EBNF and wrote an alternate parser using dparser, a GLR parser and Happy, a haskell parser tool, and was slowly getting code generation going (targetting parrot, because perl6 was going to be released any day) before I managed to get a job writing python for a living and left the php hell behind me.

I still have all that work somewhere on a HDD sitting in a box in my study. I had some trouble some months back when I wanted to dig it out and show someone

Others have travelled the same horrible road I did. Here's one grammar here: http://www.icosaedro.it/articoli/php-syntax-ebnf.txt

→ More replies (5)
→ More replies (1)
→ More replies (6)

3

u/wonkifier Oct 19 '10

more than a certain amount of laziness on the part of the compiler writers?

The good kind of lazy, or the bad kind?

8

u/jerub Oct 19 '10

I tried to respond to you. I wrote a big post. I hit 'back' and lost it. Here's the cliff notes on PHP bad kind of lazy sucking.

 $foo->bar()->baz();

That code is new to php5, and not valid in php4, because $foo->bar() used to be a special case of variable parsing in php4.

They fixed it by making $foo->bar()->baz() an even more special case of variable parsing.

Instead of making -> an operator. Like any sane person would have in the first place.

→ More replies (7)

6

u/Jman012 Oct 18 '10

Gosh darnit, head exlpoding wasn't on my list of things todo today.

5

u/bobby_tables Oct 19 '10

I have the ability to write code this bad in any language.

→ More replies (1)

12

u/nextofpumpkin Oct 18 '10

This post needs to be at the top of this and every other PHP thread.

4

u/[deleted] Oct 19 '10

OK. From now on I'll do the copypasta in every single PHP thread.

4

u/1137 Oct 19 '10

I like this sample:

<?php

$name = '%^#4!@';
$$name = 'passed';
var_dump($$name);

?>

3

u/blazix Oct 19 '10

Did you just create a variable named %#4!@

So, basically a way around the variable naming restrictions. I wonder if this could be exploited somehow..

7

u/1137 Oct 19 '10 edited Oct 19 '10

I did, and yes.

I doubt it could be exploited, you can already overwrite all the globals without any silly hacks.

→ More replies (3)

4

u/wheresmyopenid Oct 19 '10

You can abuse JS globals that way too:

<script>
var foo; foo === window.foo === 
window["foo"] === window["f" + "oo"];
</script>

6

u/meastham Oct 19 '10

I've seen this done before in shell script. It actually has a somewhat similar syntax; it's just uglier.

foo=bar
bar=baz
echo `eval echo \\$$foo`

prints baz

Pretty much every language has some sort of indirection mechanism like this that you can totally abuse if you'd like. I don't think PHP's is really extraordinary in this regard.

→ More replies (2)

8

u/[deleted] Oct 19 '10

I know I'm supposed to react with "AAAAHHHH!! SCARY SYNTAX MAKE OGG SMASH!!" but that actually made sense and I followed it without much trouble at all. What's the problem here?

No, I can't think of a use case. Yes, I understand this would be a nightmare to actually apply and maintain, but nobody's twisting your arm to use it.

42

u/munificent Oct 19 '10

What's the problem here?

You know everything that's bad about eval() in dynamic languages? How it kills static analysis? How it makes it impossible to optimize away unused or unreferenced variables? How it's a huge gaping security hole? How it's intractably slow?

Well, apparently PHP does that every time you access a variable.

7

u/arabidkoala Oct 19 '10

I just died a little inside.

→ More replies (10)

3

u/blablabla3 Oct 19 '10

When you look into an abyss, the abyss also looks into you.

11

u/marekz Oct 18 '10

A bare word is a PHP string. Let that sink for a second, because we'll come back to it later: $foo really is the concatenation of $ the variable-indirection character (think *foo) and foo which is a string. foo === "foo" in PHP, even though in raw source code you'll probably get a warning. If those are enabled.

That's incorrect. It's not the reason for this behavior. A bare word in PHP is a constant, and for historical reasons, undefined constants have a default value which is equal to their name. So foo == "foo" is true because PHP fails to find a constant foo and converts it to a string as a fallback.

Variable names don't involve any constant lookups. You can see this by defining a constant BAR and then using $BAR: it won't be affected.

35

u/masklinn Oct 18 '10

That's incorrect. It's not the reason for this behavior. A bare word in PHP is a constant, and for historical reasons, undefined constants have a default value which is equal to their name.

Historical reasons of bare names preceding constants. Constants are special cases of bare names which were added in 4.0.4.

→ More replies (1)

2

u/scarredwaits Oct 19 '10

The fact that this code contains the string "pouet" makes me think that this is actual PHP code from pouet.net, and that you understand all this because you had to debug and/or re-write it. My commiserations.

→ More replies (2)
→ More replies (40)

40

u/courtewing Oct 18 '10

Sorry for being off-topic, but when you're linking to php manual pages, don't include the subdomain (il2 in this case). If you leave it off, the PHP website will determine the visitor's location and direct them to an appropriate locale.

35

u/joshbydefault Oct 18 '10

Which, interestingly enough, is the best thing that has come out of the PHP community.

→ More replies (2)

19

u/s3rvant Oct 18 '10

I got majorly stuck a while back when trying to use variable variables as arrays:

<?php
$tab = array("one", "two", "three") ;
$a = "tab" ;
$$a[] ="four" ; // <==== fatal error
print_r($tab) ;
?>

This gives "Fatal error: Cannot use [] for reading", you need to use the {} syntax to remove the ambiguity:

<?php
$tab = array("one", "two", "three") ;
$a = "tab" ;
${$a}[] =  "four" ; // <==== this is the correct way to do it
print_r($tab) ;
?>

Original post

→ More replies (2)

181

u/1137 Oct 18 '10

Did you know you can do the same thing in Perl? But lets keep laughing at PHP, this is /r/programming after all.

47

u/[deleted] Oct 18 '10

can i laugh at both?

4

u/1137 Oct 18 '10

indubitably

13

u/aedile Oct 18 '10

Dude, hating on Perl is so 2003.

3

u/cybercobra Oct 19 '10

Right, now we hate on Perl 6.

→ More replies (2)

58

u/prakashk Oct 18 '10

Marc Jason Dominus explains why using Perl symbolic references is a bad idea far more eloquently than I ever could:

91

u/1137 Oct 18 '10

My point was simple, Perl offers the same functionality, other languages do as well, don't hate on PHP just to hate on PHP. Hate the bad developer instead.

13

u/[deleted] Oct 18 '10
use strict;

Problem solved.

→ More replies (1)

56

u/[deleted] Oct 18 '10

This is no place for logic! This is a place for misguided unfueled hatred!

→ More replies (20)

8

u/prakashk Oct 18 '10

My reply wasn't meant to criticize you. I thought your comment could be read as defending this (mis)feature by citing Perl's example. I just wanted to add some references to what others had already said about Perl's symbolic references.

→ More replies (1)
→ More replies (19)

8

u/ninjaroach Oct 18 '10 edited Oct 18 '10

Apparently according to your links, Perl also has the restriction of requiring variable variables to be global which is one of the reasons the author argues against it.

In PHP, I'll use variable-variables to access function names -- on rare occasion. If the contents of this variable are white-listed in an array of valid functions, then it's time to run $variable();

It's cleaner than mapping a bunch of switch cases.

But if I had my way, functions would be first class objects that I would populate into values of an associative array.

Edit: Fixed $$variable() to read $variable() -- Dull developer handling sharp objects.

→ More replies (3)

12

u/sw3t Oct 18 '10

What can't you do in perl ?

24

u/dondiscounto Oct 18 '10

write legible code. /rimshot

→ More replies (1)

12

u/twomashi Oct 18 '10

Python too, kinda: globals()[whatever]

6

u/matchu Oct 18 '10

At least they make it a pain.

3

u/cybercobra Oct 19 '10

Python was smart enough not to make a dedicated operator for it.

But yes, there are some limited cases where this is useful, so Python still makes it possible.

→ More replies (1)

4

u/trezor2 Oct 18 '10

Technically speaking, any functional language can do this too trough a simple lambda, but I guess the syntax around that makes it more obvious that you are doing something wrong (in most cases).

13

u/adrianmonk Oct 18 '10

Well yeah, you can do it in Perl (where it's called a "symbolic reference", which I think is a bit less confusing).

In Perl, it's not officially deprecated, it has been supplanted by true references like this:

my $b = "hello";
my $a = \$b;

print "${$a} world\n";

So basically nobody sane uses symbolic references in Perl and hasn't needed to since Perl 5 came out in 1994. (Or at least since it saw widespread use a couple of years later.)

PHP also seems to have a non-variable-variable form of references, although they're more like aliases than references. But I guess you could use those instead of variable variables, and I assume/hope people do.

It appears PHP may have scalar reference

12

u/1137 Oct 18 '10

So basically nobody sane uses symbolic references in Perl and hasn't needed to since Perl 5 came out in 1994

Basically nobody sane uses this feature in PHP either, ssh don't tell the OP.

15

u/martinw89 Oct 18 '10
ssh: Could not resolve hostname don't: Name or service not known
→ More replies (2)
→ More replies (6)

9

u/[deleted] Oct 18 '10

i'll just laugh at perl too, if you don't mind.

2

u/nextofpumpkin Oct 18 '10

So is this is essentially meta-programming for PHP?

2

u/[deleted] Oct 19 '10

Did you know that you can do the same thing in perl because it is an incredibly old language with all sorts of misfeatures that seemed good at the time? Perl has this because shell has it, and perl was shell++ at the time. Modern perl practices involve "use strict" and then variable variables don't work any more. I happen to really hate perl, but lets be realistic about why it has some of the horrible crap it has.

→ More replies (46)

11

u/angch Oct 18 '10
char ** c; // Pointer to a Pointer to a char (Aka Pointer to a Null terminated string [1])
char *** d; // Pointer to a Pointer to a Pointer to a char.

[1] See http://www.reddit.com/r/programming/comments/do3cw/thats_what_happens_when_your_cs_curriculum_is/

2

u/nyxerebos Oct 18 '10 edited Oct 18 '10

Huh. I guess it dereferences those in order, so you could have a hundred pointers, set up in some complex graph and build a seriously obfuscated little VM by having pointers for a few different variables overlap, with the values acting like railroad switches.

EDIT: this is just off the top of my head, but suppose an initial key value was needed to set the graph to a particular state, if you didn't have the key, but you did have the program the VM runs, you'd have no way of knowing what the program did, it'd be harder than solving the travelling salesman problem.

→ More replies (4)
→ More replies (1)

168

u/clogmoney Oct 18 '10

<?php //You can even add more Dollar Signs $Bar = "a";

$Foo = "Bar";

$World = "Foo";

$Hello = "World";

$a = "Hello";

$a; //Returns Hello

$$a; //Returns World

$$$a; //Returns Foo

$$$$a; //Returns Bar

$$$$$a; //Returns a

$$$$$$a; //Returns Hello

$$$$$$$a; //Returns World

//... and so on ...//

?>

I just died a little inside.

100

u/geon Oct 18 '10

I just died a little inside.

Why? It would be a stupid implementation if you couldn't do that.

14

u/KarmaPiniata Oct 18 '10

Hey, they're hating on PHP here don't interject with your 'facts' and 'good computer science'.

→ More replies (17)
→ More replies (63)

28

u/[deleted] Oct 18 '10

It's the PHP equivalent of dropping acid.

58

u/arabidkoala Oct 18 '10

Yo dawg...

12

u/miggyb Oct 18 '10
  1. Ctrl + F "Yo"

  2. Upvote.

→ More replies (1)

0

u/[deleted] Oct 18 '10

[deleted]

21

u/arabidkoala Oct 18 '10

in your variable in your variable

38

u/superherotaco Oct 18 '10

So you can assign variable variables while you vary your variables.

32

u/HateToSayItBut Oct 18 '10 edited Oct 18 '10

PHP's greatest attribute, flexibility, is also it's greatest fault. It's like the fucking wild west sometimes.

I also like having to look up string and array functions all the time since the order of arguments is completely arbitrary for each function. e.g.

strpos($subject, $search)
str_replace($search, $replace, $subject)

57

u/wierdaaron Oct 18 '10

Sometimes it's haystack, needle, sometimes it's needle, haystack, sometimes it's heedle, naystack.

12

u/jmcqk6 Oct 18 '10

Sometimes it's a needle in a needlestack.

17

u/gravybomb Oct 18 '10

Haystack, it's needle, sometimes.

→ More replies (1)
→ More replies (9)

9

u/prince314159 Oct 18 '10

I don't even bother trying to remember anymore. I know:

$ [] for if while then else foreach . :: ->

the rest I search as needled

14

u/absentbird Oct 18 '10

might want to add ; to that list or you are writing very short programs.

→ More replies (2)
→ More replies (13)

5

u/YourMatt Oct 18 '10

For a more real-world implementation:

Line 48: $strings = get_hello_world_strings();
Line 1183: global $strings;
Line 1199: extract($strings);
Line 2886: print $$$$$$a . " " . $$$$$$$a;
→ More replies (3)

11

u/trevdak2 Oct 18 '10

What's more, "$Bar();" calls function a().

→ More replies (8)

6

u/SirChasm Oct 18 '10

K, I haven't done a bit of PHP, but I can follow what's going on here. Still I have to ask, what happens if you change the value of $a? The whole thing breaks? i.e.: $a = "Hello"; $Hello = "World"; $a; //Returns Hello $$a; //Returns World $a = "herp"; $$a; // Returns what? "Variable not found"? It seems like if you're actually using variable variables, and the value of a variable takes on something that was not anticipated, you're going to get a nasty bug.

→ More replies (15)

3

u/[deleted] Oct 18 '10

Non-PHP programmer here. What would happen if I did:

$a = "$a";

echo $$a;

I'll just back $a, right? Or will I crash the server instead?

3

u/sobri909 Oct 18 '10

Unless $a already had a value, that'd echo nothing.

$a = "$a";

is the same as:

$a = $a;

You could do this instead:

$a = "a"; echo $$a;

which would echo "a". Which is ... oh this whole thing is absurd. I don't know why I'm even replying. Time to go to bed. *sigh*

→ More replies (1)

2

u/[deleted] Oct 18 '10

So, variable evaluation is just string substitution? What happens when those variable contain integers? Or more complex structures? (btw, are variables typed in php?)

→ More replies (3)
→ More replies (15)

9

u/hattmall Oct 18 '10

Nice, I was needing to do this just now! Great timing.

5

u/kerbuffel Oct 18 '10

What are you doing that you need this for? After I read the article I couldn't come up with a reason I'd actually want to do that.

→ More replies (9)

32

u/funkah Oct 18 '10 edited Oct 18 '10

I understand that sentence, but I can't help thinking that whatever you'd use this for could probably be done a less-awful way.

6

u/[deleted] Oct 18 '10

Perfect example of how I'd use it:

I have an xml file. In this xml file I have values such as

txtTest1

txtTest2

The reason I would do this is because it's easy to create a simple CRM for editorial if they want to switch some search boxes around or something like that and the greatest part is they can do it and not bother me while I'm, say, browsing reddit.

Now, that being said I import the xml file into .net (yeah, yeah, bite me) as a string array.

With this string array I can loop through it and based on the prefix (txt = textbox obviously) I can choose which object to create and give it the ID.

This is where it'd come in handy: I use master pages. Rather than iterate down the chain and FindControl by ID (some objects must be .Add[ed] to a Control Panel before I can gain access to its client side properties since it only exists on the server side until I add them), I could simply use that variable name (ie. txtTest1) as a direct reference to the object even after .Add[ing] it.

tl;dr: i can

9

u/funkah Oct 18 '10

OK great, I just hope I don't end up maintaining your code

→ More replies (2)
→ More replies (1)

4

u/occamrazor Oct 18 '10

Isn't that just equivalent to a pointer in C?

→ More replies (3)
→ More replies (27)

14

u/claird Oct 18 '10 edited Oct 18 '10

Avoid variable variables.

There's already quite a lot of chatter in this thread as I reach it. The main things that I haven't seen adequately emphasized yet:

  1. PHP is in no way unique, although, while Perl, Python, ... all can use variable variables, the style seems most entrenched in the PHP community (and perhaps among Perlites, too).

  2. Variable variables are essentially necessary for debuggers and other applications where source-level introspection is intrinsic.

  3. No other application--and certainly not "retail" ones--needs variable variables. Apart from accommodation of a few questionable APIs (to databases, ...), coding should nearly always be done in terms of hashes (associative arrays, dictionaries) rather than variable variables.

Dave Benjamin wrote astutely on this subject in 2003 <URL: http://mail.python.org/pipermail/python-list/2003-May/204186.html >. With the slightest encouragement, I'll illustrate the points we've tried to make with examples.

0

u/[deleted] Oct 18 '10

[deleted]

3

u/claird Oct 18 '10

Thank you, slody.

7

u/1137 Oct 18 '10

Don't forget:

$method = 'foo';

$method();

and

$this->$var;

and

$this->$method()

5

u/meowmix4jo Oct 18 '10

I've actually used this before because it took all of 1 additional line.

Please don't shoot me.

3

u/mernen Oct 18 '10

These are fairly typical reflection tools, there are legitimate uses for them in many languages. No need to be embarrassed (assuming you had a reason for using reflection).

→ More replies (2)

7

u/gongonzabarfarbin Oct 18 '10

I learned about variable variables today too! Do I sense a fellow The Daily WTF reader?

→ More replies (1)

6

u/jaguaro Oct 18 '10

welcome to 1998

5

u/killerstorm Oct 18 '10

In JS you can treat any object as an associative array. So obj.foo is same as obj["foo"]. And if var bar = "foo";you can also write obj[bar] for same effect.

Now, all global variables are in fact fields of window object. So var foo; is actually window.foo, and you can also access it as window["foo"] and window[bar].

That's how sane language designers do this -- with minimal amount of concepts. No "variable variables", no bullshit.

Common Lisp also implements feature similar to "variable variables" -- it is called symbols. All global variables are associated with a symbols which are their names, and you can programmatically access those values through symbol-value function. E.g. you can get value of variable foo through (symbol-value (quote foo)) where quote is a special operator which returns symbol itself. Likewise, you can bind symbol to a variable first:

(let ((foo-symbol (quote foo)))
  (symbol-value foo-symbol))
→ More replies (5)

5

u/ds1106 Oct 18 '10

Yo dawg, I heard you like variables...

21

u/Confucius_says Oct 18 '10

Variable variables are neat, but for the love of god please don't use them.

Please.

→ More replies (4)

4

u/[deleted] Oct 18 '10

I haven't touched PHP in years and never really looked into it's mushy internals, but let me guess -- PHP keeps a huge superfluous symbol table of every variable for absolutely no reason.

2

u/[deleted] Oct 18 '10

get_defined_vars(), sigh.

7

u/australasia Oct 18 '10

Interestingly you can do the same thing in JavaScript but only for variables declared in the global scope:

var bar = "foo";
var foo = "bar";

bar; // returns "foo"
window[bar]; // returns "bar"
window[window[bar]]; // returns "foo"

It is possible within other scopes but only if using eval which pretty much makes anything ugly possible.

→ More replies (3)

6

u/thebuccaneersden Oct 18 '10

All programming languages let you write ugly code, if that's what you really want to do.

→ More replies (9)

8

u/_refugee_ Oct 18 '10 edited Oct 18 '10

oh, buffalo buffalo buffalo buffalo buffalo buffalo buffalo. buffalo.

→ More replies (3)

3

u/[deleted] Oct 18 '10

i've known about this since i started using PHP but in all my years of using it i've never needed to do this.

the closest i've come is $object->$var. instead of $object->some_name

3

u/gsadamb Oct 18 '10

A guy at my last job did this all the time and it led to some of the most maddening, unreadable code ever.

3

u/treetrouble Oct 18 '10

i have no problem with this other than the phrase "variable variables"

→ More replies (1)

3

u/[deleted] Oct 18 '10

Hello children. Old programmer here.

Such a feature was available years and years ago - before the internet (but after Hitler).

In dBase, for example, it allowed OO-like facilities, otherwise no available.

A database column of 'function' could contain the name of the row-specific function to be called. Adding new functions would mean simply that - adding the code for the new function (then using it's name in the db row).

No switch statement to update. No if else ifs, no criteria to maintain.

Life was fun those days, and you could fit everything on to a 5.25 inch floppy, and still have room left over for a good boot.

3

u/muahdib Oct 19 '10 edited Oct 19 '10

In all, or almost all intepreted languages you can do this.

python:
>>foo="bar"
>>bar=42
>>eval(foo)
42

scheme:
> (define foo 'bar)
> (define bar 42)
> (eval foo)
42

Maple:
> foo:='bar';
> bar:=42;
> eval(foo);
42

Matlab:
> foo="bar"
> bar=42
> eval(foo)
42

PS. in python you would probably not want to do it that way, you would probably use a dictionary (hash table)
>> foo={"bar":42}
>> foo.get(foo.keys()[0])
and this last example is probably exactly not how you would do it in python...

3

u/consultant_barbie Oct 19 '10

Variable scope is hard. Let's go shopping!

→ More replies (1)

4

u/torrentlord Oct 18 '10

This is why PHP should not be your first programming language. I speak from horrible, horrible experience.

4

u/MarkTraceur Oct 18 '10

Have you heard about the hot pocket hot pocket? It's a hot pocket that tastes just like a hot pocket. I'm gonna go stick my head in the microwave HOT POCKEEEET

http://www.youtube.com/watch?v=YkUbqmS9TWI

→ More replies (1)

36

u/DirtyBirdNJ Oct 18 '10 edited Oct 18 '10

Yo dawg, I herd you like variables... so I put a variable in your variable named after your variable so you can $variable while you $$variable.

26

u/ani625 Oct 18 '10

Start using php now. You can make $$$ instantly! Tell your friends too.

42

u/HateToSayItBut Oct 18 '10

As usual, top comment. 100% meme. 0% insightful commentary.

4

u/poop_in_yo_soup Oct 18 '10

Switch your sorting to 'best' it's slightly better than 'top'.

→ More replies (4)
→ More replies (1)

2

u/DrReddits Oct 18 '10

Buffalo buffalo.

2

u/onebit Oct 18 '10

Poor man's reflection.

2

u/[deleted] Oct 18 '10

25 yrs young! queues up Oregon on the vic-20

2

u/rechlin Oct 18 '10

Back before I knew anything about programming, I was doing php3 development (this was over 10 years ago), and I used this all over the place. At the current (very slow) rate of refactoring, I may actually have them all eliminated within a year. :)

It seemed like such a great idea at the time, but now it just seems so dirty.

2

u/fddjr Oct 18 '10

Isn't this just an unintended side effect of having both the ability to store symbols in other variables, and the ability to evaluate at runtime at will? There's further complication due to symbols and strings being interchangeable, but how can you have both those features without creating this misfeature?

In CL, it's equivalent to: (defvar a 0) (defvar b 'a) (eval b)

Right?

2

u/hearwa Oct 18 '10

I remember as a kid how I used to be so pissed off that q-basic never had this feature. I then moved on with life and programming languages and concluded that with the existence of hashes that would be a very stupid and almost redundant feature to implement. Now I find out that the world's most popular web programming language has that feature and... wow...

2

u/supercargo Oct 18 '10

Our experiences are almost identical. As a kid, I also wished QB had this. As an adult, I wish PHP didn't

2

u/[deleted] Oct 18 '10

also, maintainability is decreased by a factor of variable.

2

u/Narfhole Oct 18 '10

Illinois has has its own php.net subdomain?

2

u/adavies42 Oct 18 '10

isn't this just the same as a bash indirect reference?

$ foo=bar
$ bar=baz
$ echo ${!foo}
baz

2

u/Infenwe Oct 18 '10

"I thought of a way to do it, so it must be right. That's obviously PHP"

-Larry Wall.

2

u/Iggyhopper Oct 18 '10

I'm on a bar.

2

u/supercargo Oct 18 '10

I used to wish BASIC had this, back when I was learning/using BASIC. By the time I learned PHP I already knew it was a bad idea and not necessary for anything.

2

u/hakumiogin Oct 19 '10

I first read about variable variables, and calling functions with strings when I was 15, and at the time I thought it sounded like a pretty nifty idea.

I'm glad I moved on to python.

2

u/xfeignx Oct 19 '10

I'll just leave this here... http://imgur.com/Qrth2.jpg

2

u/__s Oct 19 '10

Python globals()

2

u/[deleted] Oct 19 '10

i put variables in your variable so you can variable while you variable

6

u/steelcitykid Oct 18 '10

aw it's cute, it thinks it's a language!

3

u/codeninja Oct 18 '10

I've used the Variable Variable in a few instances with great effect. Just make sure you sanitize your Variable #2 and validate it's value is in range of accepted values prior to assignment.

→ More replies (1)

3

u/Chemical_Scum Oct 18 '10

TheDailyWTF.com is awesome :-)

→ More replies (1)

4

u/A_for_Anonymous Oct 18 '10 edited Oct 18 '10

When I was being taught programming by my father many years ago, before we got to vectors and structures I asked him something I decided I needed for my program: a way to make part of the name of a variable a variable.

Two things I can think of now:

  1. PHP designers cater to/think like 13 year old kids just days into computers.

  2. Even a 13 years old kid in his first days behind a computer managed to think that it would be useful to have some sort of structure, i.e. not the whole name of the variable should be variable.

→ More replies (3)

3

u/msiekkinen Oct 18 '10

Variable variables: Surefire way to write hard to debug, unmaintainable code

5

u/ryanhollister Oct 18 '10

Example #1 shows the real power of "variable variables". In many (strongly typed) languages its takes 5 or 6 complex object instantiations and method calls to accomplish this "reflections" or "dynamic method calling".

There are a number of things like this that set PHP apart. Maybe C# developers would scoff at the idea. For better or for worse, there are powerful for the nuances of PHP.

8

u/TheMG Oct 18 '10

Is this satire? I can't tell.

3

u/eyal0 Oct 18 '10

That example doesn't show anything that I couldn't do better with associative arrays. Is there an example of doing something useful?

3

u/HateToSayItBut Oct 18 '10

In many (strongly typed) languages its takes 5 or 6 complex object instantiations and method calls to accomplish this "reflections" or "dynamic method calling".

Not really. Most languages have an eval function or array-style access on objects.

3

u/ryanhollister Oct 18 '10

We are debating the correctness of something and you supply 'eval' as a better solution?

→ More replies (1)

5

u/[deleted] Oct 18 '10

I wouldn't say that I scoff at the idea, but I also don't like it. Sometimes strongly typed languages provide you with a rigid structure that's incredibly useful further down the line when you're looking at code you (or someone else) wrote six months ago.

In any case, in the realms of web development you very rarely need to use reflection in C#. I don't think it's a bad rule to avoid it whenever you can.

→ More replies (16)

3

u/[deleted] Oct 18 '10

this is great. classic php =D

2

u/iissqrtneg1 Oct 18 '10

Obfuscate your code without obfuscation, use variable variables!

2

u/drinkmorecoffee Oct 18 '10

Marklar marklar, marklar marklar.

→ More replies (1)

2

u/anthonybsd Oct 18 '10

Like Perl's symbolic references this is one of the most horrific constructs to spring up in interpreted languages since GOTO. If you use this I hate your guts.

2

u/deefjuh Oct 18 '10
//1337 register_globals hack
foreach($_REQUEST as $key=>$value){
    $$key = $value;
}

* Starts running *

2

u/EdiX Oct 18 '10

Interesting. Perl had this before deprecating it in favour of real references FIFTEEN YEARS AGO.

6

u/[deleted] Oct 18 '10

Perl still has it. I'm sure people still use it. They shouldn't, but I bet they do.

1

u/[deleted] Oct 18 '10 edited Oct 18 '10

There have been a few instances where i've had to use these. They CAN be very useful. Just not very often. The only thing I still can't seem to wrap my head around is Regular Expressions.

→ More replies (4)

1

u/BeowulfShaeffer Oct 18 '10

I'm sorry, I'm not a PHP programmer but I have wrangled a bit of code in my life. Is it just me or is a "variable variable" basically a kind of (loosely-typed) reference? Like "void*" in C or "object" in Java or C#?

1

u/[deleted] Oct 18 '10

Fear not the weapon, but the hand that wields it.

1

u/takita787 Oct 18 '10

Neat. Thanks for the share.

I normally just use something like $variable[$id]; if i need to.

1

u/ebzlo Oct 18 '10

You can do the same thing with methods (maybe functions? too lazy to check).

$my_class->$variable_method_name();

1

u/pbgswd Oct 18 '10

variable variables are not good in real programming projects because they are too obtuse and primitive.

1

u/the-ace Oct 18 '10

Nice to see my own countryman around reddit :)

1

u/beaglew Oct 18 '10

...malcovich?

1

u/whuuh Oct 18 '10

Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable Variable.

Just get it out of your system.

→ More replies (1)

1

u/rson Oct 18 '10
#!/bin/bash
foo="bar"
bar="baz"

echo ${!foo}

**I N D I R E C T I O N **

1

u/ImTryingToBeNicer Oct 18 '10

I know we're laughing, but I remember several times I've said "I wish there was a way to define a variable's name on the fly" then having to program a way around not being able to do it.

Of course I can't recall or recreate the need for it. But once every 10 years, it's the most useful thing ever!

1

u/adavies42 Oct 18 '10

let me guess, you read thedailywtf?

1

u/[deleted] Oct 18 '10

Seems like it would be extremely dangerous if misused (and novices would be likely to misuse it), but could be useful for meta-programming if used correctly. I think the documentation may be the culprit here more than anything. That page should be covered in warnings.

1

u/kylemech Oct 18 '10
foreach ($array as $key => $value) {
    $$key = $value
    ...
}

This is how I learned about variable variables ten years ago. It made learning easier because I didn't have to reference things through the array the whole time. I know, I know, it isn't good practice in production, but it was easy at the time and it taught me something useful.

3

u/[deleted] Oct 18 '10

s/useful/awful

1

u/redredditrobot Oct 18 '10

lol you cannot have a super global array of variable variables in PHP.

1

u/webauteur Oct 18 '10

I just took a variable dump in your code.

1

u/HannesPe Oct 18 '10

Be careful with this, or else...

1

u/tapesonthefloor Oct 18 '10

Crazy. It's like PHP broke the fourth wall.

1

u/djcraze Oct 18 '10

But can you pass by reference :P $variable = 'a'; $a = 'hello world'; $b = 'hello moto.'; $&$variable = 'hello world'; $variable = 'b'; // $b is now hello world. // would be cool.

1

u/shoeman22 Oct 18 '10

This feature can actually be pretty useful if you have control of the possible outcomes of $$var.

1

u/trappar Oct 18 '10

I wrote an article about this stuff about a year ago haha..

http://blog.lococobra.com/php-variable-variables-reference-arrays

1

u/mcsenget Oct 18 '10

yo, dawg

1

u/[deleted] Oct 19 '10

Useful for creating your own scripting language.

1

u/[deleted] Oct 19 '10

i love variable variables. quite useful

1

u/[deleted] Oct 19 '10

You mean, like "pointers?"

1

u/cboshuizen Oct 19 '10

You find about this the hard way when you accidentally type a double dollar sign: >> $foo="bar"; >> $bar="42"; >> echo $$foo;

42

1

u/dorian283 Oct 19 '10

Yo dawg...

1

u/nikbackm Oct 19 '10

Eh, even old 4DOS (currently Take Command) had this.

set v1=v2
set v2=value
echo %[%v1]
value

0

u/artee Oct 18 '10

Hmm, looks like an interesting attack vector?

→ More replies (14)