Object References

There is no other way to put it other than to say that dealing with object references in PHP is just plain nasty. Not only was it confusing to begin with, recent API changes in PHP4 >= 4.4 and PHP5 >= 5.1 have made the situation even more confusing. I will do my best to explain what you need to know on this page, however, it might be a good idea to check out the References Explained of the PHP manual.

Simple Explaination

Variables are passed when moving in and out of functions, and when being assigned to other variables. The are two way to pass these variables in PHP. By default, PHP will take the value represented by your variable, copy it, and then pass the result along as an assignment in the new context. However, it is possible to instruct PHP to pass it as a reference. This means that instead of making a copy of the value, it will point the new variable to the same value that the old variable points two. Now both of the variables are pointing to the same value. In many cases, the distinction is transparent since the program will be none the wiser. For instance, this distinction is completely irrelevant for primitives, since there is no way to change the value by operating on it. (Primitives can only be assigned, not changed). When it really starts to matter is when you are dealing with objects. Making a copy of an object could be detremental to the program because different areas of the code could be updating different instances of the object. Since the Studs framework is highly object-oriented, references become very important.

That Funny Symbol

You know you are looking at code that is dealing with references when you see the & symbol preceding a method declaration or next to an assignment operator.

function &find() {
  $result =& lookCloser();
  return $result;
}

The first thing to note is that it is up to the programmer to manage references, and it is a huge pain! One missed & and the program could start to exhihit very strange behavior because an object was copied when a reference was supposed to be handed off instead. In addition to dealing with the & symbol, there are several other rules that make life difficult. A couple of these rules were introduced in recent releases of PHP and broke the 0.9.7 release of Studs very badly.

Restrictions

The rule is simple. Only variables can be passed by reference. While it may sound simple, this is an extremely invasive and restrictive rule because it imposes the responsibility on the developer rather than the interpreter. If the & symbol is being used to indicate a reference should be passed, the thing being passed must be a variable, nothing else. Let’s look at cases that are not permitted to understand why.

  • A method marked to return a reference cannot return a primitive type.
function &callMe() {
  // illegal!
  return null;
 
  // legal
  $nil = null;
  return $nil;
}
  • A method marked to return a reference cannot return another method call.
function &callMe() {
  // illegal
  return callAnother();
 
  // legal
  $result =& callAnother();
  return $result;
}
  • A method marked to return a reference cannot return an expression.
function &callMe() {
  // illegal
  return "result: " . callAnother();
 
  // legal
  $result = "result: " . callAnother();
  return $result;
}
  • A method marked to return a reference must not be void (return no value).
function &callMe() {
  // illegal
  return;
 
  // legal (must remove the & since it isn't necessary)
  return;
}
  • A variable cannot be assigned a reference to a primitive type (nor does it make much sense)
// illegal
$foo =& null;
  • A variable cannot be assigned a reference to a method call that does not return a reference
// illegal
$foo =& trim(" bar ");
  • A variable cannnot be assigned a reference to an expression
// illegal
$foo =& "foo" . trim(" bar ");
  • A primitive cannot be passed as an argument requiring a variable reference
function callMe(&$arg) {
}
 
// illegal
callMe(null);

Nagging "Notice" Errors

So, what happens when your code violates these rules? If PHP notice errors are enabled, and your application has a mechanism for handling or otherwise displaying these errors, you will encounter a message similar to the one listed below:

Notice: Only variable references should be returned by reference in /path/to/script.php on line 100

The trick is to check out that file and line number and figure out which of the above rules is being violated. Of course, you could always disabled notice errors, but such practice is typically discouraged since future versions of PHP could up the ante on this violation.

A Convenient Hack

In order to make life a bit easier, I added an convenience method in Studs named ref. This method simply tricks the interpreter into thinking it is dealing with a variable by reference when really it is dealing with either primitive value or an expression.

function &ref($value) {
  return $value;
}

Now it is possible to use a primitive inline with a variable reference by wrapping it in the ref function call. A perfect example of when this is useful is when null needs to be returned for a function that would otherwise return a reference to a variable. Consider the case of a lookup function. If the value is not found, ref(null) will be returned.

function &lookup($id) {
  // search but couldn't find
  return ref(null);
}
 
howto/object_references.txt · Last modified: 2006/12/31 06:11 by 69.255.155.127 (dallen)
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki