简体   繁体   中英

How to determine if a pass-by-reference variable is set?

For an arbitrary function declared as follows:

function foo($first, &$second = null) {
    // if ($second is assigned) {
    //     Work with $second
    // }
}

How does one determine if $second is indeed assigned to a variable at call time, eg.:

foo('hello', $second);

vs

foo('hello'); // Notice &$second is unassigned

Tried isset() , is_null() but they don't seem to work.

Update:

Created a test script here here

It's my understanding that you wish to implement a function that implements something like preg_match , whereby the third argument gets populated with the memory patterns if passed.

Internally, PHP functions use a function called zend_parse_parameters() ; it accepts a format string and a variable number of arguments that will be populated with the meta data of the call parameters. If a parameter is not passed (eg when it's optional), the meta data is not available and thus is easy to detect.

Coming back to PHP itself, unfortunately there's no such thing as func_arg_used($var) that will tell you if $var was passed as a function argument; perhaps this would be an interesting contribution to the language, but until then you'll have to settle for something more ancient :)

if (func_num_args() > 1) {
    // $second was passed and can be used to populate
}

You may have to be careful when changing the signature of the function, especially when you add parameters in front of $second ; however, naturally this shouldn't happen often because it would most definitely break dependent functions. Adding more arguments at the end has no effect on above code.

There are two ways you can go with this:

  1. ReflectionFunction - the shiny new toy of developers, it allows you to introspect your function and determine whether the signature changed from when it was created. Use it sparingly though, introspection is not cheap, especially considering the alternativey.

  2. The humble code comment - the much understated form of code policing; a simple line that says // IMPORTANT - don't add arguments before $second

You can't (as far as I know) tell the difference between NULL and Undefined using isset. You could set default value of $second to some random value that will never be used otherwise.

define('UNDEFINED', -19181818);

function foo($first, &$second = UNDEFINED) 
{
 if($second==UNDEFINED)
 {
  etc..
 }
}

Works for me :

<?php

function bool_str($b)
{
    return ($b ? "true" : "false");
}

function foo($first, &$second = null)
{
    echo bool_str(isset($first)) . " " . bool_str(isset($second)) . " " .
         bool_str(is_null($first)) . " " . bool_str(is_null($second)) . "\n";
}

$a = 1;
$b = 2;

foo($a, $b);
foo($a);

?>

Output:

true true false false
true false false true
     ^^^^^       ^^^^

Which is precisely what I would expect, ie you can use both isset and is_null here.

I think the suggestion by Jack to use func_num_args () is excellent.

function foo($first, &$second = null) {
    if (func_num_args() > 1) {
        //$second MUST be assigned
    }
}

This properly detects when $second references a variable which exists in the calling scopes' symbol table, yet it has a variable value of null.

$second = null;
foo('hello', $second);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM