0

Can someone explain to me why this strange thing is happening? I have an empty $_POST array and i want to use a variable in that array that might be defined or not (in that case - use some default value). To do so, i have a function to avoid using all those isset() or empty() checks:

function val(&$varToCheck, $defaultValue = false)
{
    if (isset($varToCheck))
        return $varToCheck;

    return $defaultValue;
}

Now if i say:

val($_POST['test']); print_r($_POST['test']);

The $_POST array now contains a NULL value key "test". I assume this is happening because the variable is passed by reference and somehow auto-creates an array index. How could i avoid this behaviour?

4
  • Why do you need reference for $varToCheck? Commented Jul 14, 2014 at 9:12
  • what is the php version, AFAIK in 5.3 u need to use this val(&$_POST['test']); print_r($_POST['test']);, and remove & sign from function declaration Commented Jul 14, 2014 at 9:13
  • @KA_lin i don't need to reference it, it's just the only way i know of avoiding E_NOTICE. Commented Jul 14, 2014 at 9:17
  • @dav My PHP version does not allow call-time passing by reference. The reference needs to be in the function. Commented Jul 14, 2014 at 9:17

2 Answers 2

2

Yes. That will work so because you're using a reference in your function. That will create array index. Shorter way to illustrate:

$array = [];
$foo = &$array['foo'];

Array is now:

array(1) {
  ["foo"]=>
  &NULL
}

So index was created. That's how references work (when creating that references you increase refcount by one).

And - no: it is impossible to implement isset() with a custom user-land function. That is because references in PHP are not pointers. You can not maintain scope with references.

You may use wrapper for arrays like

function valArray(array &$array, $index, $defaultValue = false)
{
    if(array_key_exists($index, $array) && !isset($array[$index]))
    {
        //note, having index & having it set isn't same
        $array[$index] = $defaultValue;
    }
}

So check if index exist first. Usage is like:

$array = ['foo'=>null];
valArray($array, 'foo', false);
valArray($array, 'bar', true);
//var_dump($array);

Then your array won't have additional indexes after such check. But - this also uses references, it's tricky way and it reduces readability. I strongly recommend to use direct isset() checks instead.

Sign up to request clarification or add additional context in comments.

5 Comments

Yep, i could use it, but that's another function to create and 2 arguments to pass by, which is not as convenient as it could be. Sad that php doesn't have any built in thing to do this. Thank you for your help though.
"Alma Do" you were first :) +1 for valArray($array, 'foo') . I agree with "Alma Do". I really think that you are doing it with the wrong way. I don't think that it is Sad that PHP doesn't have any built in thing to do this. I think this is a good thing , you have your notice :)
Yes. PHP has special things for that (so, upvoted @deceze's comment)
BTW: "because references in PHP are not pointers" - even if they were pointers... how do you pass a pointer to a potentially non-existing element into a function? :)
I'll admit that I'm not very experienced in low-level languages and what exactly the usage patterns of a pointer are in detail, but in terms of PHP... how do you get the offset to an undefined element in an array, whether as pointer or otherwise...?
0

That's how call-by-reference works. Take this example:

function foo($bar, &$error) { ... }

foo('bar', $error);

echo $error;

The point of this pattern is that the variable $error will be created in the calling scope and will be populated with error codes, so you have access to them later. So yes, your array key will be created for you if it doesn't exist.

What you are trying to do is simply nonsensical.

function foo($bar) {
    isset($bar) ...
}

The isset check within this function is entirely nonsensical, since $bar is declared right there in the function signature. The variable is absolutely guaranteed to exist. You cannot use this construct to test whether some variable in the calling scope was set or not, whether you pass by reference or not. The variable exists within the function and is entirely independent of anything in the calling scope. You're only passing values into the function, not the variables themselves.

You have to use isset directly on the $_POST array in the calling scope, you cannot defer that into a different scope.

The only alternative is to pass the array and key separately:

val($_POST, 'test')

function val(array $array, $key) {
    isset($array[$key]) ...
}

2 Comments

I expected as much. Is there any universal short way to get the value of a variable (or default value if unset) without getting E_NOTICE? It is really annoying to test each value with isset().
Well, no. You need to use isset when you need to use isset. See kunststube.net/isset for some in-depth discussion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.