germi germi - 1 month ago 6
PHP Question

iteration variable inside for changing its value

I'm facing something I don't understand, I've tried many things. The weird thing is that this happens only in some servers, but not on others. So I'm guessing is somehow related to the PHP config. I have this code:

$j = 0 ;
for($m = $days - 1; $m >= 0 ; $m--){
$time1 = strtotime('-'.$m.' DAY');
$date_day = date('Y-m-d', $time1) ;

$$items_var[$j] = new stdClass();

$j++;
}


The value of $days is 7. So this is for loop where $m goes from 6 to 0. well.. it should be. it starts ok, it does 6,5,4,3... and then it crashes. usually the error I get is
Catchable fatal error: Object of class stdClass could not be converted to string

so, at some point (and it looks random, because in some servers is after the second iteration), the $m becomes an object...!!

this is somehow related to that assignation you see on the code:

$$items_var[$j] = new stdClass();

Yes, that's a double $$. I have a variable $items_var which value is "items". Therefore I'm trying to create this new stdClass() in an array called $items.

this is what's messing the code, but I don't know why. If I remove this assignation, the code works. the $m goes from 6 to 0. but for some reason, some PHP installations are messing this up and this line of code CHANGES the value of $m to an object.

I am clueless.

Answer

It's EXACTLY this:

Yes, that's a double $$. I have a variable $items_var which value is "items".

That means you have:

$items_var = 'items';

And you're using that string as an array:

$$items_var[$j] = new stdClass();

When $j = 3, you're effectively running

$m = new stdClass();

and have now overwritten your for loop variable with an object. On the NEXT iteration, you end up doing

stdClass() >= 0

and produce your exact error.

This is exactly WHY you should NEVER use variable-variables. You end up with stupid/impossibly difficult-to-debug errors like this.


comment followup:

PHP allows strings to be treated as arrays of characters:

$foo = 'abcdefgh';
echo $foo[3] // outputs 'd'

Variable variables take the contents of a variable, and use it as the name of some OTHER variable:

$bar = 'hi mom';
$foo = 'bar';

echo $foo;  // outputs 'bar'
echo $$foo; // outputs 'hi mom'

So given:

$items_vars = 'items';
$j = 3;

This sequence occurs:

$$items_vars[$j] = new stdClass();
 ^-------------^
        |
$   'items'[3]   = new stdClass();
        |
$       m        = new stdClass();

$m = new stdClass();

and boom, your $m that you're using in for($m=....) is now trashed.


code deconstruction. If you pull apart your loop and write it out longhand:

$items_vars = 'items';
$j = 0;
for($m = $days - 1; $m >= 0 ; $m--){
    $$items_var[$j] = new stdClass();

You end up doing this:

               $$items_vars[$j]     = new StdClass:
j = 0; m =6    ${'items'[0]}  -> $i = new stdClas();
j = 1; m = 5   ${'items'[1]}  -> $t = new stdClass();
j = 2; m = 4   ${'items'[2]}  -> $e = new stdClass();
j = 3; m = 3   ${'items'[3]}  -> $m // BOOM

You're not putting your new stdClass objects into an array. Your variable-variable is building SINGLE LETTER variable names, and putting a stdClass into each of them. If you want to store your new classes in an array, you'd need something more like

array_push($$items_var, new stdClass());

which would execute as

array_push($items, new stdClass());
Comments