Debugging PHP: Part II – References

Posted October 28th, 2012 in Razno by Metod

If you read around the internets, you will see alot of references are bad stuff. Well, they are if you deal with them in the wrong way. Let’s take a look at an example:

  1. <?php
  2. // …
  3.  
  4. foreach ($all_regions as &$regions) {
  5.     $regions[‘en’] = array_replace($regions[‘ascii’], $regions[‘en’]);
  6.     unset($regions[‘ascii’]);
  7. }
  8.  
  9. // alot of lines of code here
  10.  
  11. foreach ($all_regions as $country_id => $cultures) {
  12.     foreach ($cultures as $culture => $regions) {
  13.         // …
  14.     }
  15. }
  16.  
  17. // …

Just a simple code to replace any missing english translations with the ascii ones. For which we decided to use a reference. Which is all good, except … !

Can you spot the problem?

In the second nested foreach, in the second run of that foreach we get an error that the supplied value is not an array. But we know it is an array! So what is happening here?

Well, that reference we used has bitten us. Remember, how the values assigned in foreach loops do not get unset when we leave that foreach scope? The problem is that the &$regions did not get unset automatically and we kept that reference all the way down to that problematic foreach. In the first run of the second foreach we then effectively appoint the value of $cultures to the $all_regions variable, replacing it’s original array values. Thus we get the error.

What was the correct code?

Just unset the reference.

  1. <?php
  2. // …
  3.  
  4. foreach ($all_regions as &$regions) {
  5.     $regions[‘en’] = array_replace($regions[‘ascii’], $regions[‘en’]);
  6.     unset($regions[‘ascii’]);
  7. }
  8.  
  9. // this only unsets the reference, not the variable it is pointing to
  10. unset($regions);
  11.  
  12. // …

And the problem goes away. These kinds of bugs are hard to spot. Especially since there is quite some code between the two. So when using references keep in mind: Always unset your references once you’re done with them!

Debugging PHP: Part I – Type casting

Posted October 27th, 2012 in Razno by Metod

Here and there I run into some interesting bugs which I think would be nice to share. So here goes, bug #1 – Type casting.

  1. <?php
  2. $type = ‘sometype’;
  3.  
  4. // …
  5.  
  6. $entity->setSync((int)$type === ‘sometype’);
  7.  
  8. // …
  9.  
  10. if ($entity->getSync()) {
  11.     // this should be run
  12. }
  13.  
  14. // …
  15.  

Can you spot the problem? That if never gets evaluated. Why?

The problem is here:

  1. $entity->setSync((int)$type === ‘sometype’);

In this case, the (int) cast only casts the $type variable, not the whole expression. So (int)$type === 0 which definitely is not equal to ‘sometype’ and also since we are using strict checking, type int is not equal to type string. The result is always boolean false.

The correct line should be:

  1. $entity->setSync((int)($type === ‘sometype’));

So watch out with casting and parenthesis.