PHP 5.0.5: Fatal error: Only variables can be passed by reference

Published September 13th, 2005

A fairly obscure issue has been generating a lot of heat in the PHP community recently. With the release of PHP 4.4 and 5.0.5, a change has been made to the engine that has resulted in some new errors popping up in existing code. Check out this previously-acceptable snippet:

function getAnArray() {
$myArray = array ( 1, 2, 3 );
return $myArray;
}
echo( array_pop( getAnArray() ) );

Where in the past this would have resulted in the output ‘3’, now you get this:

Fatal error: Only variables can be passed by reference

(in fact it’s only a warning in v4.4). It’s not exactly unusual practice to return an array from a function in this way, and to be honest I wasn’t even aware that this constituted a reference until this error arose. Here’s an ugly fix:

function getAnArray() {
$myArray = array ( 1, 2, 3 );
return $myArray;
}
echo( array_pop( $my_temp_variable= getAnArray() ) );

This works because it assigns the return value to a variable before passing it to array_pop(), hence avoiding the whole “is it a reference or isn’t it?” issue. Yuk.

Anyway I was curious as to why such a change would be made, and so I’ve been reading lots of blogs, bug reports and such. The core of the issue seems to be a long-standing memory corruption issue, which is fixed by this change. Well that’s fair enough I suppose, but what has really shocked and surprised me as I’ve been reading is the attitude of the developers of PHP.

Instead of presenting this as an unfortunate but necessary change, the reaction has been along the lines of “It’s not our fault your apps are now broken, you wrote bad code.”. A comment from one of the most active insiders on the PHP bugs list was particularly illuminating:

Instead of ranting about things…you should try to understand the engine instead. Then you see exactly what the problems are. If you don’t want to spend time on that, then just stfu, okay?

[A comment by Derick Rethans (a member of the PHP development team), in response to this blog entry on PHP Everywhere]

So apparently all PHP developers should have been aware (somehow) of the internal workings of PHP, known that this sort of construct would have caused an error, and avoided using it (even though it was permitted, and even — if I recall correctly — appeared in various places in the documentation)? I hardly think that’s a realistic expectation. Then there’s this:

There’s nothing critical here, fix your scripts.

[From this bug report]

I find this stance hard to swallow, and it has led to much discussion within our team as to whether we should continue using PHP as our development platform. Yes this is a relatively minor issue (although it took several hours of developer time to track down all the occurrences in our extensive codebase, and we’re still waiting for more to pop up) but if it’s indicative of how PHP’s development is heading, then it’s worrying. How long is it going to be before we’re informed that another previously valid construct is no longer permitted — and that it’s our own fault for using it? How much time can we afford to waste going back over stable code to fix these problems?

At this point, we are seriously looking at the feasibility of freezing our codebase and moving to an alternative platform for development. This isn’t a hot-headed, knee-jerk reaction: it’s a considered response to legitimate commercial concerns.

Get a Trackback link

6 Trackbacks/Pingbacks

  1. Pingback: StickBlog » Blog Archive » PHP variable reference problems: further insight on September 15, 2005
  2. Pingback: Hossie’s Blog » PHP 5.0.5 und mal wieder was Neues on November 3, 2005
  3. Trackback: blog.BUZZZED.de on December 8, 2005
  4. Pingback: And the PHP soap opera rumbles on… » StickBlog on November 28, 2006
  5. Pingback: NextGEN Gallery ???????? Fatal error: Only variables can be passed by reference | ? Shian's Blog on July 27, 2008
  6. Pingback: Caso Real: PHP 5.0.5: Fatal error: Only variables can be passed by reference (y Solucion) | Fortman.info on July 24, 2009

23 Comments

  1. leonid on October 22, 2005

    I have too same problem with php 5.0.5

    PHP Fatal error: Only variables can be passed by reference in

    this:

    $ref_contenu_message = $pop -> headerinfo ($pop -> msgno($msgnum), $ev);

    I dont understand what I need change ??? Pleas help !

  2. Stickman on October 23, 2005

    If I understand the situation correctly, one of the functions you’re calling takes one or more its parameters as a reference. You’re passing in the return value from a function, which you can’t do any more because it’s not a variable. Assign all function return values to a variable before passing them to another function and it should solve the problem.

    Something like this:


    $msg_no = $pop -> msgno( $msgnum );
    $ref_contenu_message = $pop -> headerinfo ( $msg_no, $ev );

  3. Diego on November 4, 2005

    My problem is pass this while block to php 5:

    while( $fetched_result_array = $xoopsDB->fetchArray( $prs ) ) {
    $xoopsTpl->append_by_ref( ‘photos’ , myalbum_get_array_for_photo_assign( $fetched_result_array , true ) ) ;
    }

    The page come blank and php show the fatal error.
    I´ve tried change to:

    while( $fetched_result_array = $xoopsDB->fetchArray( $prs ) ) {
    $temp = myalbum_get_array_for_photo_assign( $fetched_result_array , true );
    $xoopsTpl->append_by_ref( ‘photos’ , $temp ) ;
    }

    But the pictures doesn´t changes (it´s a picture module of Xoops CMS). This code is repeating the picture listening and i want to change the pictures (see in website url: http://www.rebenta.com.br/modules/myalbum/).

  4. ATOM on November 26, 2005

    In PHP 5.1 is this again OK

  5. Stickman on December 8, 2005

    As far as I’m aware, no change to this behaviour has been made between 5.0.5 and 5.1.x. So the ‘only variables can be passed by reference’ error will still occur.

  6. AJ on January 30, 2006

    I’ve been caught out by this problem just now after only being forced to upgrade php. By now most of the scripts have been updated, however there is one i’m struggling with. Can anyone help me with this please:

    $userid = $names_idx->get_count ( ) == 0 ? 1 : current ( $names_idx->get_last ( ) ) + 1;

  7. Matt on August 28, 2006

    cheers, that article helpped a lot. I was totally stumped on that error until I found this.

  8. Mikhail on September 9, 2006

    something that has just worked for me:

    $firstDirName = array_pop((explode(‘\\’, $dir)));

    this is on Windows machine; notice double parenthesis;
    essentially saying “take the output of explode and work with it”

  9. Mike on September 29, 2006

    I suggest people stop pouring effort into php. It’s very evident that the people that work on the core language just can’t think clearly. Like a bunch of drunk and stoned teenagers or something. I’d fire people like that in a hurry, it sucks.

    Why not take all the php stuff, and move over to Perl? Similarish syntax, but at least consistent. It’ll perhaps as good, if not better, and it’s written by *much* smarter people.

  10. J on November 8, 2006

    The double () around the reference works great as Mikhail indiocated. Here is an example I have to get a random record:

    Changed:
    current(fJumpTo($objSponsors, $randNum))

    to

    current((fJumpTo($objSponsors, $randNum)))

  11. S on November 10, 2006

    I’m having the same problems in PHP 5.x.

    I’m finding it hard to find a pretty way around this.

    Any tutorials or anything?

  12. naisioxerloro on November 29, 2007

    Hi.
    Good design, who make it?

  13. Joel on November 29, 2007

    here is the line I am having problems with in my script

    $ext = strtolower(end(explode(‘.’, $file_name1)));

    and here are some lines before and after.

    $file_name1=$_FILES["image"]["name"];
    $ext = strtolower(end(explode(‘.’, $file_name1)));
    if($ext!=”jpg”&&$ext!=”jpeg”&&$ext!=”png”&&$ext!=”tif”&&$ext!=”gif”)
    {
    print “Err# The image format you uploaded is not supported by our system.“;
    print “Add more photos“;
    print “Return to home“;
    }

    else
    {

    $picture_name=$_SESSION["member_id"].$picture_id.”90998″.”.”.$ext;
    $picture_url=”user_images/”.$picture_name;
    $result = move_uploaded_file($_FILES["image"]["tmp_name"], $uploaddir.$picture_name);

    Any suggestions on correcting this line:

    $ext = strtolower(end(explode(‘.’, $file_name1)));

  14. Joel on December 1, 2007

    Any suggestions of getting this code re written?

    $my_temp_variable = strtolower($file_name1);

  15. Dev Null on June 27, 2008

    > So apparently all PHP developers should have been aware
    > (somehow) of the internal workings of PHP

    Um, yeah. They should. Just as anyone working in any language should be aware of the internals of that language.

    One of the reasons that PHP developers don’t get much respect (and by and large don’t deserve much) is because most don’t have any knowledge of the basics of programming – such as the difference between passing by value and passing by reference. Anyone with training in a lower-level language such as C or Java understands that, but people whose previous “programming” background is limited to HTML won’t.

    One of PHP’s greatest virtues is that it is a dead-simple language to learn. One of PHP’s greatest weaknesses is that it is a dead-simple language to learn. And as a result, probably 95% of the PHP code out there is utter crap.

  16. Stickman on June 30, 2008

    Wow, a rave from the grave!

    > Um, yeah. They should. Just as anyone working in any
    > language should be aware of the internals of that language.

    I don’t agree. A programming language should be self-explanatory: if it’s doing something wrong behind the scenes then that the fault of those who wrote the language, not those who are using it.

    When I wrote this article I wasn’t arguing against the fix. What concerned me was the attitude of the PHP developers when announcing it, trying to blame the users rather than take responsibility for the error themselves. If the construct was causing problems, it shouldn’t have been legal in the first place.

  17. Evan on November 18, 2008

    An array is an object, not a variable, and objects are passed by reference, not duplicated. Thus it’s absolutely necessary to duplicate it before using something like array_pop by first setting the variable.

    This one threw me for a loop for a while as well, and I didn’t even notice there was an issue until I implemented a customer error handler on one of my sites.

    ** changing code ** …

  18. Dave on January 17, 2009

    Stickman, you’re right. Dev Null, you’re wrong. People learn by example, and if the official examples out there are flawed from the outset, then it’s not the end user that is wrong. The attitude from the php dev is completely wrong; the arrogance is heavily misplaced.

    Thanks for pointing out the fix anyway, Stickman.

  19. Christopher Shennan on March 27, 2009

    Thanks guys. Couldn’t understand why I had this working before but was having problems now.

  20. Andreas on April 28, 2009

    For me the change makes sense cause it is clearer now than before. A Reference has to be a var. Northing more.
    But I understand: its annoying that old code suddenly doesn’t work anymore.

    However, litte help for those having trouble (example with sort() wich works with a reference).

    Old (->will lead to error):
    > sort(array(2,3,1));

    Correct for newer PHP:
    > $array = array(2,3,1);
    > sort($array)
    or
    > sort($array = array(2,3,1))

  21. Shan Shui on July 2, 2009

    If you do sort($array = array(2, 1)); while on E_STRICT, you will get this message:

    Strict Standards: Only variables *should be* passed by reference

    *as opposed to “can be” on a fatal error

    So basically, PHP has an order of preference in regards to this issue:

    Recommended – $array = array(2, 1); sort($array);
    Still accepted – sort($array = array(2, 1));
    FATAL ERROR!!! – sort(array(2, 1));

  22. Danitza on August 5, 2010

    Thank you so much!!!

  23. THANK YOU on November 26, 2010

    THANK YOU, I was spending HOURS to find why it worked sometimes and others it didn’t.

    1000 Thanks

Leave a comment

Comment Policy: First time comments are moderated. Please be patient.

OpenID

Anonymous