How to handle references in PHP 4.4.0

valiant

Joined: 2003-01-04
Posts: 32509
Posted: Sun, 2005-07-17 20:17

I'm working on making G2 PHP 4.4.0 compatible. The "new" PHP rules for references are rather silly IMO, but they exist now. See: http://www.php.net/manual/en/language.references.return.php
So here are a few guidelines to obey PHP's rules:

assigning by reference
sample code:
correct:
$example =& $b;
correct:

$example =& test();

function &test() {
    $val = 'foo';
    return $val;
}

incorrect:

$example =& test();

function test() {
    $val = 'foo';
    return $val;
}

In the last example, the function was defined to no return by reference.
If you assign by reference, the function you get the value from has to return by reference!
Else you get the following PHP Notice:Notice: Only variables should be assigned by reference in fileName/lineNumber

A mistake that I found often in the smarty / adodb code:
incorrect:
$foo =& array_merge($a, $b);
correct:
$foo = array_merge($a, $b);
incorrect:
$foo =& mysql_fetch_array($result);
correct:
$foo = mysql_fetch_array($result);

returning by reference
sample code:
correct:

$example =& test();

function &test() {
    $val = 'foo';
    return $val;
}

correct:

$example = test();

function &test() {
    $val = 'foo';
    return $val;
}

Notice that you can assign by value or by reference, it doesn't matter. If you assign by value, it will just copy the variable.

incorrect:

function &test() {
    return null;
}

correct:

function &test() {
    $ret = null;
    return $ret;
}

incorrect:

function &test() {
    return array();
}

correct:

function &test() {
    $ret = array();
    return $ret;
}

incorrect:

function &test() {
    return 1;
}

correct:

function &test() {
    $ret = 1;
    return $ret;
}

incorrect:

function &test() {
    return 'string';
}

correct:

function &test() {
    $ret = 'string';
    return $ret;
}

incorrect:

function &test() {
    return array(GalleryStatus::success(), $foo);
}

incorrect:

function &test() {
    return $ret = array(GalleryStatus::success(), $foo);
}

correct:

function &test() {
    $ret = array(GalleryStatus::success(), $foo);
    return $ret;
}

incorrect:

function &test() {
    return (string)$this->_somevar;
}

correct:

function &test() {
    settype($this->_somevar, 'string');
    return $this->_somevar;
}

incorrect:

function &test() {
    return foo();
}
function &foo() {
    $bar = 'bla";
    return $bar;
}

correct:

function &test() {
    $ret =& foo();
    return $ret;
}
function &foo() {
    $bar = 'bla";
    return $bar;
}

Else, you'd get this PHP notice:
Notice: Only variable references should be returned by reference in fileName/lineNumber

Summary
There are just two simple rules to remember:

1. If you are assigning by reference, make sure the function on the right (if it's a function), is returning by reference.

2. If you create a function which is returning by reference, make sure all return statements in this function are of the pattern "return $varName;". Don't create new variables in the return statement and don't return constant values like null, 1, ... just return; or expressions.

 
mindless
mindless's picture

Joined: 2004-01-04
Posts: 8601
Posted: Tue, 2005-07-19 03:31

Thanks valiant.. I see the fixes for G2 are now in cvs.

 
valiant

Joined: 2003-01-04
Posts: 32509
Posted: Mon, 2005-12-05 11:07

In PHP 5.1.0 some changes were corrected. Particularely, return otherFunction(); is allowed again, as long as the other function also returns-by-reference.
That means that the following code doesn't need to be changed for PHP 5.1.0+ . But since we're offering G2 for PHP 4.4.0+ too, we still can't do something like that without the above mentioned fix in G2.

function &test() {
    return foo();
}
function &foo() {
    $bar = 'bla";
    return $bar;
}

pass by reference
PHP 5.0.5+ is also more strict about passing values by reference. e.g. in PHP 4.3.11 if you did for some reason:

$myVal = array_pop(foo());
function foo() {
    return array('foo', 'bar', 'baz');
}

you'll have it to change for PHP 5.0.5+ to

$myArray = foo();
$myVal = array_pop($myArray);