this post was submitted on
2 points (52% like it)
20 up votes 18 down votes
all 27 comments

[–]warmans 26 points27 points ago*

Could you not have formatted the code any better? It's really hard to figure out what you're trying to show - particularly given that using empty and isset on an array with string values works fine.

Edit: actually having read the code below and testing it this still acts the same way under PHP 5.3. Weird - I'd like to know why....

Edit 2: Okay I think it's because strings can be used as arrays but they don't work exactly as expected so...

$test = 'value';
if(isset($test['x'])) {
    echo 'is true '.$test['x']; //outputs is true v
}

I believe the reason is that 'x' is cast to an integer when doing the comparision so it will always just return what's at position 0 in the string - in this case "v". I don't know why it does the cast though if that's what it's doing. So it would seem you need to be careful not to use array comparisons on strings.

[–]d4v1d04 15 points16 points ago

This is an actual skype conversation from earlier today (edited the names out). please take this knowledge and run with it friends. btw, we are still running php 4.2

[colleague]

$testArray = array("index"=>"value");
if(isset($testArray["index"]["crap"]) && !empty($testArray["index"]["crap"])) {
  echo "true [{$testArray["index"]["crap"]}]\n";
} else {
  echo "false";
}

[colleague] returns true

[me]

php > $test = "value";
php > echo $test["crap"];
v

[me] hehe because value is an array

php > echo (int)"crap";
0
php > echo $test[(string)"crap"];
v

[me] haha

[me]

php > $test = array("index"=>"value");
php > echo array_key_exists("crap", $test);

[me] there you go

[me] array_key_exists is ftw

Cleaned it up a bit...

[–]thelerk[S] 2 points3 points ago

Thanks! well done. next time I will use a better medium. I just hope that the moral of the story isn't lost on my terrible reddit formatting

[–]Samus_ 3 points4 points ago

be a good guy thelerk and edit your submission so others can understand it :)

[–]HaywoodMullendore -2 points-1 points ago

This is an actual skype conversation from earlier today (edited the names out). please take this knowledge and run with it friends. btw, we are still running php 4.2

[colleague]

$testArray = array("index"=>"value");
if(isset($testArray["index"]["crap"]) && !empty($testArray["index"]["crap"])) {
  echo "true [{$testArray["index"]["crap"]}]\n";
} else {
  echo "false";
}

[colleague] returns true

[me]

php> $test = "value";
php> echo $test["crap"];
v

[me] hehe because value is an array

php> echo (int)"crap";
0
php> echo $test[(string)"crap"];
v

[me] haha

[me]

php> $test = array("index"=>"value");
php> echo array_key_exists("crap", $test);

[me] there you go

[me] array_key_exists is ftw

[–]jous 4 points5 points ago*

Strings can be manipulated as arrays, like

$test = 'value';
echo $test[1] . $test[2]; // prints 'al'

Since strings are not the same thing as regular php associative arrays, the value will be force cast to integer. It would be nonsensical to name string character positions. How would you even do it? 'one', 'two', 'three'? C'mon now. http://php.net/manual/en/types.comparisons.php shows quite clearly that when a non-empty string "php" is converted to ingeter, it maps to 0 (zero).

Because the type system is dynamic, it has plenty of features like this. IMHO strings behaving somewhat same as arrays is not very useful, as I always use substr for clarity, but I can understand the temptation to add these kind of features to a language.

[–]uxp 5 points6 points ago

This.

People need to learn how memory is managed in the languages they use. PHP takes a hand from C's arrays, which would work something like this

char *foo = "foo bar";

printf("%c", foo[0]);
printf("%c", foo[1]);
printf("%c", foo[2]);

results in "foo" being printed.

Nearly the same exact idea is happening with this PHP code. This Is How It Is Supposed To Work. If you are writing code like:

var $foo = "bar";
doSomethingWithBar($bar)
$foo[$bar];

and $bar is not null, then you are a bad programmer and need to learn not to overload operations on variable types that do not support the overloading you are trying to do. Plain and simple.

[–]warmans 0 points1 point ago

I wasn't trying to say that you SHOULD be able to use string keys when using a string as an array - rather that it just shouldn't bother doing the cast to integer then the thing would work more or less as expected. But I guess it's a moot point given it has been fixed anyway.

[–]thelerk[S] -1 points0 points ago

yea, the small reddit text entry box is not conducive to sharing code samples. In retrospect, I should have used a gist. After I posted, I realized that my point was probably lost.

[–]judgej2 2 points3 points ago

As well as switching to a more recent version of PHP, it looks like you need to upgrade your browser too. Most browsers these days let you stretch text area boxes to whatever size you like.

[–]ChiperSoft 0 points1 point ago

It's perfectly conducive to code samples, you just need to learn markdown. Any text indented by four spaces is parsed as a code block:

such as this text.

You also need to end a line with three spaces to get it to insert a line break
Like so.

Otherwise you need a double line break to create a new paragraph.

[–]nikic 8 points9 points ago

PHP 5.4 will change this behavior. "foo"["bar"] will throw a notice and isset("foo"["bar"]) will return false.

By the way, if you are still using PHP 4.2, you REALLY REALLY should switch.

[–]BornInTheCCCP 0 points1 point ago

Reminds of the time I upgraded a server from 4 to 5. That was one fun week.

[–]thelerk[S] -3 points-2 points ago

I would love to, but 5.3 has enough breaking changes from 5.2 that it's impossible.

[–]wvenable 2 points3 points ago

I'm confused, are you running 4.2 or 5.2? I'm surprised you would have trouble going from 5.2 to 5.3 -- I'm currently running 5.3 in development and 5.2 in testing/production without any compatibility issues.

[–]grobolom 1 point2 points ago

I must disagree. I've been in charge of running the upgrade at my job from 5.2 -> 5.3, and I've found that other than a bunch of [Notice] and [Warning] messages, there is nothing in 5.3 that won't allow 5.2 code. Hell, we've still got pg_exec and pg_numfields (no underscore there; it's that old) in our codebase and 5.3 runs just fine.

[–]skwigger 3 points4 points ago

He's on 4.2, not 5.2

[–]BTMPL 4 points5 points ago

Yeah, but in the comment he's talking about breaking changes in 5.2 => 5.3 thus the confusion.

Also, on a fun note, I've had to migrate a server full of websites (also hosted our clients) from 3.x to 4.x and SQL 3.x to 4.x FUN TIMES!

[–]stonedoubt 0 points1 point ago

ditto... I have so many older projects on my server (I host clients) that I can't switch. I tried it once and it broke a lot of stuff. :P I was in notice hell.

[–]dahlma 1 point2 points ago

You should be turning errors off in production mode anyway.

I kind of see the upgrade plan laid out as follows:

* Write code with PHP 5.1 have server be PHP 5.1
* PHP 5.2 is released
* Install PHP 5.2 locally
* Test all sites locally, fix errors as needed
* Announced planned downtime
    - Plan for an early morning upgrade
* Update PHP on live server, or test server if possible
* Push out code to all new sites
* Be thankful that you don't have to hope there is old documentation floating around on Google, since you're using the latest and greatest

[–]ChiperSoft -1 points0 points ago

So disable notices... Notices are just there to help you realize where you could be making mistakes. Anything that triggers a notice is non-critical to site operation.

[–]k3n 2 points3 points ago

Best explanation I could find:

It's actually very simple. Take variable $a which is a string ("foo"). Now it you do $a[0] that would produce first letter - "f". Now here's a tricky part - if you do $a['blah'] it would convert 'blah' to number, get 0 and return the same letter "f".

Now what happens if you do $a[0][0]? Since $a[0] is "f", $a[0][0] should be first letter of "f" which is "f" again, right? Only in 5.3 it did not work because of some deficiencies in implementation of string offsets. In 5.4 it was fixed.

Now the situation in the bug - what happens if we do $a['blah']['foobar']? As we noted before, it's the same as $a[0][0] and thus produces "f" in 5.4. In 5.3 it didn't work because of the above deficiency. That's it.

Relevant discussion, related post, bug report against 5.4, and related, and related...

[–]steelaz 2 points3 points ago*

PHP 5.4

error_reporting(-1);

$test = 'value';

// Returns bool(false)
var_dump(isset($test['x']));

// Throws warning - Illegal string offset 'x' 
// Returns string(1) "v"
var_dump($test['x']);

PHP 5.3

error_reporting(-1);

$test = 'value';

// Returns bool(true)
var_dump(isset($test['x']));

// Returns string(1) "v"
var_dump($test['x']);

[–]ChiperSoft 0 points1 point ago

I don't get what it is you're trying to warn us here. Why would you ever use isset to test the presence of a character using a string as an index? The only knowledge I'm running with here is that you don't get the difference between a string, an array and an integer...

[–]famousmadphilosopher 0 points1 point ago

Looks like you dropped one of these: is_array