6

I've asked a question before, that essentially took the $null = null approach as a given, to returning a null reference in PHP.

After some cursory Googling, I didn't turn up much; leaving me to assume that the aforementioned approach is the best (read, only) way. However, it seems odd to me that PHP would (still) fail to support such functionality.

Anyways, if it's unclear; what (other, if any) ways exist to return null from a function by reference in PHP? I'm asking specifically about returning the null reference, not about the ternary operator issue that surfaced to explain my linked question.

For instance:

function &return_null(){
    return null;
}

$null_ref = return_null(); // fails

However:

function &return_null(){
    $null = null;
    return $null;
}

$null_ref = return_null(); // succeeds

I'm asking because I'm a bit OCD when creating reusable libraries; I really like clean code, with respect to however clean it can get in a given language. Using a placeholder $null = null makes my skin crawl, despite it achieving the desired functionality.


For the sake of completeness @yes123, here's the method snippet where this problem lives:

public static function &getByPath(Array &$array, $path, $delimiter){
    if(!is_array($path)){
        $path = explode($delimiter, $path);
    }
    $null = null;
    while(!empty($path)){
        $key = array_shift($path);
        if(!isset($array[$key])){
            return $null;
        }
        if(!empty($path) && !is_array($array[$key])){
            return $null;
        }
        $array = &$array[$key];
    }
    return $array;
}

There's also setByPath(), issetByPath(), and unsetByPath() in this ArrayPath class. I've aliased these static methods with the overloading magic. When an instance is constructed, an array is passed to the constructor (along with a delimiter), and the magic methods call the static ones using the referenced array of the instance. It's working pretty swell so far. In addition, I've written an alias function, array_path() that simply returns an instance. So for example, one can do:

$array = array(
    'foo' => array(
        'bar' => array(
            'hello' => 'world',
        ),
    ),
);

array_path($array, '/')->{'foo/bar/hello'} = 'universe';
var_dump($array);

/*
array(1) {
  ["foo"]=>
  array(1) {
    ["bar"]=>
    array(1) {
      ["hello"]=>
      string(8) "universe"
    }
  }
}
*/
Community
  • 1
  • 1
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174
  • 2
    you should make a real example of usage, because for sure there is a better way to do what you want without using references – dynamic Oct 22 '11 at 19:44
  • 1
    +1 for (seemingly) unnecessary code making your skin crawl! – Nick Brunt Oct 22 '11 at 19:44
  • @yes123 - Unfortunately no, I make quite an effort to explore all possible means to accomplish a given task; in this instance that has once again piqued my curiosity on the issue, there is no logical option other than returning a reference, or null in some cases. – Dan Lugg Oct 22 '11 at 19:48

5 Answers5

6

I'm also a bit anal about my code. There is no functional difference here but I think this looks and reads better. But that is just my personal preference.

function &getByPath(array &$array, $path, $delimiter = '/'){
    $result = NULL;

    // do work here and assign as ref to $result if we found something to return
    // if nothing is found that can be returned we will be returning a reference to a variable containing the value NULL

    return $result;
}
Daniklad
  • 945
  • 8
  • 10
  • It wouldn't feel un-easy about this, I needed to return a reference if element existed in array. I knew element might not even be there, so I check the return value for null before using it. I think this is a valid solution for a warning. – AaA Jan 22 '20 at 03:18
4

I'm not sure if "references" and "clean code" go together... :(

Anyway, references are not "pointers to" objects/values, rather, they are "pointers to" variables. Thus, only a variable is a suitable target. Said variable can "name" an object/value (read: be assigned a value), as demonstrated in the post. The post, however, does not return a "null reference" -- it returns a reference to a variable that "names" null.

(And then people wonder why I reject the terminology that a variable "stores a reference to an object" when dealing with high-level languages/concepts...)

Happy coding.

  • Thanks @pst - I guess the terminology I chose is incorrect in this context; "returning a null value (*or value of null*) by reference, in absence of an assigning name with which to reference" seemed like an invalid way of explaining it, but I suppose that answers the question itself; one cannot. – Dan Lugg Oct 22 '11 at 22:07
3

As for returning by reference, it will not work the other way

You can only return variables by reference from a function - nothing else.

http://www.php.net/manual/en/language.references.return.php

You may want to rethink if reference is something you really need, especially that you are already passing $array as reference and returning it

dev-null-dweller
  • 29,274
  • 3
  • 65
  • 85
1

I just do this (without initialising $null):

return $null;

It has the benefit of being like NikiC mentioned, where you can simply use isset($result) to determine if a result exists.

Ryall
  • 12,010
  • 11
  • 53
  • 77
1

A solution for your particular problem is to generalize your code:

function &getByPath(array &$array, $path, $delimiter = '/'){
    if (!is_array($path)){
        $path = explode($delimiter, $path);
    }

    $current =& $array;
    foreach ($path as $part) {
        $current =& $current[$part];
    }

    return $current;
}

Now no magic null values are returned. Instead the function will return the element as the path specified, even if it did not yet exist (the path will be added to the array and initialized with null).

$element =& getByPath($array, 'hallo/world');
isset($element); // if the element didn't exist, this will return false
$element = 'hi'; // we can set the element, even if it did not exist

Oh, and by the way: There is no other way to return null by reference and I also don't see why you have a problem with that ;) Returning by reference means returning a variable and, well, null aint one.

NikiC
  • 100,734
  • 37
  • 191
  • 225