PHP can be tricky sometimes …

In: PHP

17 May 2009

Some people just like to write as few line of codes as possible. Well, PHP can be tricky sometimes.. For instance, be carefull when declaring a variable and passing it as a parameter to a function or to a method at the same time. If that parameter is supposed to be passed by reference, you may end up with some unexpected behaviors !

Look at the following code, What do you think will be outputted ?

function changeStr(&$str)
{
    $str = 'foo_' . $str;
    return $str;
}

$res = changeStr($str = 'bar');

var_dump($str);
var_dump($res);

Here is the result.

string 'bar' (length=3)
string 'foo_bar' (length=7)


Surprise ! $str didn’t get passed as a reference.

So basically, $str hasn’t been affected by the changeStr() function. Let’s try with an array now..

function changeArr(&$arr)
{
    $arr['id'] = 10;
    return $arr;
}

$res = changeArr($arr = array());

var_dump($arr['id']);
var_dump($res['id']);

The result is…

null
int 10

Well, same behavior as earlier. $arr wasn’t altered by the changeArr() function !

What about objects, does it do the same thing ?

function changeObj(&$obj)
{
    $obj->id = 10;
    return $obj;
}

$res = changeObj($obj = new StdClass());

var_dump($obj->id);
var_dump($res->id);

Here is the result.

int 10
int 10

So, it doesn’t work for a string or an array, but it work with objects !

Well, I highly suggest any developer not to declare a variable and pass it to a method or a function at the same time. Just write the additional line of code, it is gonna reduce the risk of error and actually might make your core more readable !

  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks

5 Responses to PHP can be tricky sometimes …

Avatar

Pascal G.

May 22nd, 2009 at 12:46 pm

Looks like the behavior is as soon as an expression is passed as parameter, the reference is lost. I guess that what is happening is an implicit memory allocation is done to store the result of the expression and this is passed by reference instead of the variable. We cannot “see” this memory allocation because we do not have a variable defined for it. Its lifetime is then just the for function call.

For the object example, even if you do not pass the object by reference it will work because an object variable is more like a pointer. Passing an object by reference implies that you may want to change the “pointer” value (pointer of pointer). So to rewrite your last example this way would lead to the same behavior as other examples:

function changeObj(&$obj)
{
$obj = new StdClass();
$obj->id = 10;
return $obj;
}

$res = changeObj($obj = new StdClass());

var_dump($obj->id);
var_dump($res->id);

OUTPUT:
null
10

Avatar

Robert van der Linde

June 3rd, 2009 at 12:04 pm

This is basic PHP behavior and should be well known if you’ve been using PHP for a while. Objects are always passed by reference which makes sense. Literals are not

Avatar

Bashar

June 4th, 2009 at 11:10 am

Indeed, since PHP5, objects are always passed by reference.

Pascal, isn’t the behavior you are describing true in C# ?

Avatar

Pascal G.

June 10th, 2009 at 10:20 am

In C#, as soon as you define a parameter as an output parameter, the compiler will force you to pass a variable as parameter. It won’t allow expression as parameter.

Won’t compile:
stdClass res = changeObj(ref new stdClass());

stdClass obj;
stdClass res = changeObj(ref obj = new stdClass());

Will compile:
stdClass obj = new stdClass(0;
stdClass res = changeObj(ref obj);

So the only one that compiles has no ambiguous behavior.

Avatar

anis berejeb

June 14th, 2009 at 2:16 pm

I think that there is no ambiguity because what is passed in the :
$res = changeObj($obj = new StdClass());
is actually the result of the expression $obj = new stdClass(); and not $obj itself.

Comment Form

Who am I?

My name is Bashar Al-Fallouji, I work as a Enterprise Solutions Architect at Amazon Web Services (Sydney, Australia).

I am particularly interested in Cloud Computing, Web applications, Open Source Development, Software Engineering, Information Architecture, Unit Testing, XP/Agile development, etc.

On this blog, you will find mostly technical articles and thoughts around PHP, OOP, OOD, Unit Testing, etc. I am also sharing a few open source tools and scripts.

  • dipan: Hi Bashar It's really awesome that you wrote this code. IT'll save tones of time of all developer. [...]
  • Bashar: Glad that you liked it ! [...]
  • Angel S. Moreno: well, there goes wasting a couple of hours of development and a couple of days of testing. I owe you [...]
  • Bashar: Thats right, the setSaveFile create a files containing an associative array of classname => filen [...]
  • Loggy: Jim's clarification in particular was pretty useful although I did have to dig down into the tree to [...]