Perl vs. PHP : variable scoping

I’ve mentioned quite a few times that I am a big fan of Perl programming languge.  However, most of my programming time these days is spent in PHP.  The languages are often similar, with PHP having its roots in Perl, and Perl being such a influence in the world of programming languages.  This similarity is often very helpful.  However there are a few difference, some of which are obvious and others are not.

One such difference that I came up recently (in someone else’s code though), was about variable scoping.  Consider an example in Perl:

#!/usr/bin/perl -w
use strict;
my @values = qw(foo bar hello world);
foreach my $value (@values) {
    print "Inside loop value = $value\n";
}
print "Outside loop value = $value\n";

The above script will generate a compilation error due to undefined variable $value.  The one outside the loop.

A very similar code in PHP though:

#!/usr/bin/php
<?php
$values = array('foo','bar','hello','world');
foreach ($values as $value) {
    print "Inside loop value = $value\n";
}
print "Outside loop value = $value\n";
?>

Will output the following:

Inside loop value = foo
Inside loop value = bar
Inside loop value = hello
Inside loop value = world
Outside loop value = world

In Perl, variable $value is scoped inside the loop.  Once the execution is out of the loop, there is no such thing as $value anymore, hence the compilation error (due to the use of strict and warnings).  In PHP, $value is in global scope, so the last value “world” is carried further down the road.  In case you reuse variable names in different places of your program, counting on scope to be different, you might get some really interesting and totally unexpected results.  And they won’t be too easy to track down too.  Be warned.

Read 14 comments


  1. I don’t think it’s that big a deal. The only time this behaviour can cause bugs is when you set a variable with the same name as a loop item and i don’t think this is a common scenario.

    This can be the reason why none word variables, for example $i, are allowed in loops. Those variables stand out in all the clearly named variables.


  2. David,

    yes, I agree that this is not a frequently caught issue (otherwise it would either be fixed or better documented). However, when it happens, it’s not that easy to find.

    In the code that I looked at, it was not the case of a simple variable name (like $i) used elsewhere. It was the opposite -- a descriptive variable name used in the loop. I understand that for for() loops $i is probably the best choice of a name, since it’s just a counter. However, for foreach() loops more descriptive variables are often used. Having a couple of loops one after another increases variable pollution.


  3. Variable scoping in PHP is boolean, it’s either in or out of a function. It works the same way for any language construct used, not only foreach.

    The documentation is clear: “For the most part all PHP variables only have a single scope. […] However, within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope.”
    http://php.net/manual/en/...gu......scope.php


  4. You are right that in foreach loops people use a descriptive name but i think the none word name can be extended to foreach loops if the loop is in a data processing/manipulating file. Personally i use $temp and derivatives in these cases.

    If loops are in display files the loop item has to be descriptive but there spotting this sort of bug is easy.


  5. Timur,

    one scenario that I can think about where longer names can make more sense in a foreach() loop, is when working with objects, or nested data structures. Something along these lines:

    foreach ($basket as $product) {
    if ($product->in_stock) {
    $paper_type = $settings[‘present’] ? ‘nice_present’ : ‘ugly_yellow';
    $product->wrap($paper_type);
    $product->ship();
    }
    else {
    $product->suggest_replacement();
    }
    }

    Keeping $product as a long variable helps to remember methods and such. However, later on, if you do something like:

    echo $product->categories()

    You might see something you weren’t expecting to…


  6. Leonid,

    One more thing that would interest me is the performance issue related to unset(), because there is always an overhead for calling a function, right? I guess in some cases it would be more effiecient to just leave the variables there rather than unset them? Is that so or there are some hidden issues about that?


  7. After moving from Perl to PHP recently I was a little surprised by the previously described scoping issues. I prefer the Perl implementation, although I guess it’s just because I’m familiar with it.

    Global variables are another interesting one. It seems PHP protects you from accidentally referencing a variable in global scope, and you have to actively declare it with the “global” keyword before it can be used.

Leave a Reply