$theTitle=wp_title(" - ", false); if($theTitle != "") { ?>
Talks around Computer Science and Stuff
In: PHP
17 May 2009Some 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)
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 !
My name is Bashar Al-Fallouji, I work as a Enterprise Solutions Architect at Amazon Web Services.
I am particularly interested in Cloud Computing, Web applications, Open Source Development, Software Engineering, Information Architecture, Unit Testing, XP/Agile development.
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.
5 Responses to PHP can be tricky sometimes …
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
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
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# ?
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.
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.