PHP What? A Call-time pass-by-reference story

I'm jumping the gun. Drupal 7 may not be ready for production sites, but I've got a book to write and books need examples. As a result I'm migrating one of my sites from D5 to D7. Moshe has been helping me through the migrate.module and I've been trying not to rip all my hair out as I learn new ways to do things incorrectly. (Pages, CCK fields and Events are all importing correctly into D7. Book hierarchy still needs work.) Some of the work I've been doing on my local dev server, but this week I decided to upload the work to date to a public Web site for others to look at. I was greeted by a D7 date.module error:

Warning: Call-time pass-by-reference has been deprecated in /path/to/modules/date/date/date.module on line 657
Warning: Call-time pass-by-reference has been deprecated in /path/to/modules/date/date/date.module on line 665
Warning: Call-time pass-by-reference has been deprecated in /path/to/modules/date/date/date.module on line 673

I did some searching and found this error is mildly common and it's been around for a while. But it was definitely new to the date.module. I submitted a bug report. And then I kept working at it (chapters don't magically write themselves just because you've found a bug). I got some excellent help from chx and dmckenna. The date.module has implemented three new Drupal functions: hook_field_insert, hook_field_validate, hook_field_update. These three functions all have a variable that is "passed by reference." In other words: there's a little & which means you may alter the contents of a variable that was passed to a function without having to return it. cool, eh? (See also the official definition of what a PHP reference is. My definition paraphrases a little bit.)

In older versions of PHP you could send a variable to a function and indicate at "Call time" that you wanted to "assign the output of the function to the content of this variable name." In newer versions of PHP this is no longer the right way to do things. You may not set up a variable to be altered when calling a function, you may only write functions to receive variables that may be altered. Perhaps this analogy will help: on Hallowe'en night (in North America) kids go knocking from door-to-door begging for candy. Hallowe'en has been defined as the function (night) where this is acceptable. Children cannot, however, decide that today is Hallowe'en because they want candy (pass-by-reference at call time).

For module developers who are updating their functions to D7: remember not to copy and paste the functions from the API. Look closely and remove the & from variables when calling functions in your own modules. Of course, you should leave the & in when defining the function if you want to reference the variable...it's just when passing variables to the function that you need to omit the &.

For themers, deployers and regular techie folks: when you run across that call-time pass-by-reference error you can:

  1. Report a bug to the project letting them know they need to update their code to use modern PHP practices.
  2. Fix the code yourself by removing the & (this may break other things; submit your patch back to the affected project and others will help you test it).
  3. Update your server settings to turn off the warnings. By default this specific warning is turned ON; however, some hosting providers will turn it OFF (Ubuntu turns it off by default, Dreamhost turns it on by default). In your PHP config file (php.ini) find and alter the setting for allow_call_time_pass_reference. Set it to "On" to allow the code without throwing up warnings. You will need to restart your server for the changes to take effect.

And there we have it: a heads-up for developers and hopefully a set of handy tips for anyone else that's run into this problem too.

Good post. One small

Good post.

One small correction: passing a variable to a function preceded by & didn't store the output in the variable (though many Drupal functions use arguments that way), but rather passed the argument in by reference instead of by value.

That means any manipulation of the variable you do inside the function are also reflected in the variable in the scope outside the function. You can still output something completely different from the function. This might be useful, for example, if you want to pass a database connection object to a function and don't want to create a new one inside the function, but you still want to perform a query and return its output from the function while hanging on to your database connection.

The only limitation PHP 5 imposes is forcing you to do this when you declare the function, rather than doing it on the fly when you call the function in your code. Many people do it reflexively when passing in things like arrays, under the mistaken impression that they're "saving memory by not duplicating the array in memory"...but as a prominent PHP core developer pointed out, that's not really true.

http://blog.libssh2.org/index.php?/archives/51-Youre-being-lied-to..html

LOL - nice halloween analogy.

LOL - nice halloween analogy.

Oh boy...I had forgotten that

Oh boy...I had forgotten that PHP had that feature. I am certainly glad to see that it's being expunged.

Git for Teams

Git For Teams

Best selling title from O'Reilly media. Covers essential skills needed to use Git in a team environment.

Available from O'Reilly media, and better bookstores worldwide.

Collaborating with Git

Collaborating with Git

Practical how-to videos to get you, and your team, up and running with Git. A complementary video series for the book, Git for Teams.

Available from O'Reilly media.

Drupal User's Guide

Drupal User's Guide

Site building for Drupal 7. Includes in-depth information on Drupal's most popular site building modules, SEO and accessibility. Two complete case studies are included in the book along with the tools you'll need to build (almost) any Web site with Drupal.

Available from Amazon.com.

Front End Drupal

Front End Drupal

The industry go-to for learning theming in Drupal 6. A great companion to Lullabot's book, Using Drupal.

Available from Amazon.com.