Php function argument error suppression, empty() isset() emulation
Asked Answered
P

14

10

I'm pretty sure the answer to this question is no, but in case there's some PHP guru

is it possible to write a function in a way where invalid arguments or non existent variables can be passed in and php will not error without the use of '@'

Much like empty and isset do. You can pass in a variable you just made up and it won't error.

ex:

empty($someBogusVar); // no error

myHappyFunction($someBogusVar); // Php warning / notice
Purcell answered 10/9, 2008 at 19:9 Comment(4)
no idea why this has been downvoted, seems a reasonable question to meBivins
He just completely changed the question. He needs to close this and ask a new one if that's what he wants to do. He ripped out his entire example, as well.Edo
i'm not sure what the proper protocol is here on stackover flow, but if that's what i should do i'll do thatPurcell
the meat of the question was: s it possible to write a function in a way where invalid arguments or non existent variables can be passed in and php will not error without the use of '@' which is the same. I answered the question as was worded, and my answer will work for the old wording or the newBivins
C
9

Summing up, the proper answer is no, you shouldn't (see caveat below).

There are workarounds already mentioned by many people in this thread, like using reference variables or isset() or empty() in conditions and suppressing notices in PHP configuration. That in addition to the obvious workaround, using @, which you don't want.

Summarizing an interesting comment discussion with Gerry: Passing the variable by reference is indeed valid if you check for the value of the variable inside the function and handle undefined or null cases properly. Just don't use reference passing as a way of shutting PHP up (this is where my original shouldn't points to).

Chronological answered 10/9, 2008 at 20:9 Comment(9)
You're statement in bold is incorrect, please take a look at porneL's answer: https://mcmap.net/q/1045808/-php-function-argument-error-suppression-empty-isset-emulation#answer-311954Lockett
His statement in bold is not incorrect. If you've designed your functions so that you need to suppress warnings/errors caused by missing arguments, then you designed your functions wrong and need to start over. porneL's answer is a valid workaround, but it's not a good idea.Dora
I just edited my answer to correct the incorrect bold statement, I wasn't aware of the by reference trick.Chronological
It said "no you can't". It seems Vinko agrees that the statement was incorrect and has modified it, which I thank him for. It is not suppressing an error either. In the case of an undefined variable being used as an argument, it is creating a null reference, which can then be tested inside of myHappyFunction() to see if it in fact exists. I still don't agree with how this has been rewritten. You definitely should not use this technique to suppress errors, but it does have valid applications, such as the creation of an alternative empty() function as was asked for in the question!Lockett
The question didn't ask for the creation of an alternative empty() function, only for the creation of a function with empty()-like behavior with respect to undefined variables, for which the usage was not specified. I still stand by that you shouldn't. I don't think there's a need to qualify most shouldn'ts by all the possible exceptions, which always exist. If you know what you are doing you certainly can do what you should not without any harmful side effect.Chronological
Ok well I think it's only a should not if used in a bad way. As I said, it's only creating a reference to NULL, which by itself I believe is not a "should not" and it's unlikely this would have been an oversight by the PHP devs. It's the misuse of this to hide errors (which is probably how most would use it if they knew) that is a "should not". But I'm happy to agree to disagree on this. Our comments are both there so people can read them and decide for themselves. I like the revised version of your answer a lot better anyway. It says good things about you that you came back and fixed it.Lockett
The main point you are overlooking is that the question explicitly states "... a way where invalid arguments or non existent variables can be passed in and php will not error without the use of '@'." This points to the intended usage which is where we agree on "shouldn't."Chronological
Yes and if I wanted to emulate empty(), that is exactly what I would want. Because I would want to check for the validity of the variable inside of the function without triggering an error in the same way an error is not thrown when you call the official empty(). But that doesn't mean your suppressing an error, but instead coding it in a way that will not cause an error, which is what porneL's function does.Lockett
This is assuming you indeed check for the value of the variable inside the function. Doing so demonstrates that "you know what you are doing".Chronological
O
11

You don't get any error when a variable is passed by reference (PHP will create a new variable silently):

 function myHappyFunction(&$var)
 {       
 }

But I recommend against abusing this for hiding programming errors.

Observe answered 23/11, 2008 at 0:32 Comment(3)
There are many situations when this is the correct thing to do, like handling (possibly) missing incoming POST variables in a standard way. Thanks for giving an actual answer to the question!Pocky
@Purcell This should be the top and accepted answer. It precisely answers what you were asking. The accepted answer (which says "no") is incorrect because SO should have answers not opinions (i.e. no you shouldn't it).Vestment
This creates the variable in the caller and thus has side effects, which is not good practice. Use references when you need references, don't abuse them for error suppression. If you're regularly working with undefined variables, that's the real issue you need to fix. Not work around it with hacks like this.Yandell
C
9

Summing up, the proper answer is no, you shouldn't (see caveat below).

There are workarounds already mentioned by many people in this thread, like using reference variables or isset() or empty() in conditions and suppressing notices in PHP configuration. That in addition to the obvious workaround, using @, which you don't want.

Summarizing an interesting comment discussion with Gerry: Passing the variable by reference is indeed valid if you check for the value of the variable inside the function and handle undefined or null cases properly. Just don't use reference passing as a way of shutting PHP up (this is where my original shouldn't points to).

Chronological answered 10/9, 2008 at 20:9 Comment(9)
You're statement in bold is incorrect, please take a look at porneL's answer: https://mcmap.net/q/1045808/-php-function-argument-error-suppression-empty-isset-emulation#answer-311954Lockett
His statement in bold is not incorrect. If you've designed your functions so that you need to suppress warnings/errors caused by missing arguments, then you designed your functions wrong and need to start over. porneL's answer is a valid workaround, but it's not a good idea.Dora
I just edited my answer to correct the incorrect bold statement, I wasn't aware of the by reference trick.Chronological
It said "no you can't". It seems Vinko agrees that the statement was incorrect and has modified it, which I thank him for. It is not suppressing an error either. In the case of an undefined variable being used as an argument, it is creating a null reference, which can then be tested inside of myHappyFunction() to see if it in fact exists. I still don't agree with how this has been rewritten. You definitely should not use this technique to suppress errors, but it does have valid applications, such as the creation of an alternative empty() function as was asked for in the question!Lockett
The question didn't ask for the creation of an alternative empty() function, only for the creation of a function with empty()-like behavior with respect to undefined variables, for which the usage was not specified. I still stand by that you shouldn't. I don't think there's a need to qualify most shouldn'ts by all the possible exceptions, which always exist. If you know what you are doing you certainly can do what you should not without any harmful side effect.Chronological
Ok well I think it's only a should not if used in a bad way. As I said, it's only creating a reference to NULL, which by itself I believe is not a "should not" and it's unlikely this would have been an oversight by the PHP devs. It's the misuse of this to hide errors (which is probably how most would use it if they knew) that is a "should not". But I'm happy to agree to disagree on this. Our comments are both there so people can read them and decide for themselves. I like the revised version of your answer a lot better anyway. It says good things about you that you came back and fixed it.Lockett
The main point you are overlooking is that the question explicitly states "... a way where invalid arguments or non existent variables can be passed in and php will not error without the use of '@'." This points to the intended usage which is where we agree on "shouldn't."Chronological
Yes and if I wanted to emulate empty(), that is exactly what I would want. Because I would want to check for the validity of the variable inside of the function without triggering an error in the same way an error is not thrown when you call the official empty(). But that doesn't mean your suppressing an error, but instead coding it in a way that will not cause an error, which is what porneL's function does.Lockett
This is assuming you indeed check for the value of the variable inside the function. Doing so demonstrates that "you know what you are doing".Chronological
B
4

You can do this using func_get_args like so:

error_reporting(E_ALL);
ini_set('display_errors', 1);

function defaultValue() {
    $args = func_get_args();

    foreach($args as $arg) {
        if (!is_array($arg)) {
            $arg = array($arg);
        }
        foreach($arg as $a) {
            if(!empty($a)) {
                return $a;
            }
        }
    }

    return false;
}

$var = 'bob';

echo defaultValue(compact('var'), 'alpha') . "\n"; //returns 'bob'
echo defaultValue(compact('var2'), 'alpha') . "\n"; //returns 'alpha'
echo defaultValue('alpha') . "\n"; //return
echo defaultValue() . "\n";

This func goes one step further and would give you the first non empty value of any number of args (you could always force it to only take up to two args but this look more useful to me like this).

EDIT: original version didn't use compact to try and make an array of args and STILL gave an error. Error reporting bumped up a notch and this new version with compact is a little less tidy, but still does the same thing and allows you to provide a default value for non existent vars.

Bivins answered 10/9, 2008 at 19:46 Comment(3)
i still get a undefined error: Notice: Undefined variable: var2 in file.php on line 19Purcell
buggeration - you're right :) OK this version fixes it. You have to use compact to extract the variables from out of the mix (including any fantasy ones which don't exist) but should still allow for some compact code (no pun intended)Bivins
that's a clever usage of the compact function. I've never seen that in such a use, thanks for the tip.Purcell
S
3

There are valid cases where checking becomes cumbersome and unnessesary.
Therfore i've written this little magic function:

/**
 * Shortcut for getting a value from a possibly unset variable.
 * Normal:
 *   if (isset($_GET['foo']) && $_GET['foo'] == 'bar') {
 * Short:
 *   if (value($_GET['foo']) == 'bar') {
 *
 * @param mixed  $variable 
 * @return mixed  Returns null if not set
 */
function value(&$variable) {
    if (isset($variable)) {
        return $variable;
    }
}

It doesn't require any changes to myHappyFunction().
You'll have to change

myHappyFunction($someBogusVar);

to

myHappyFunction(value($someBogusVar));

Stating your intent explicitly. which makes it good practice in my book.

Sidonnie answered 8/12, 2009 at 14:46 Comment(0)
H
1

No, because this isn't really anything to do with the function; the error is coming from attempting to de-reference a non-existent array key. You can change the warning level of your PHP setup to surpress these errors, but you're better off just not doing this.

Having said that, you could do something like

function safeLookup($array, $key)
{
  if (isset($array, $key))
    return $array[$key];

  return 0;
}

And use it in place of array key lookup

defaultValue(safeLookup($foo, "bar"), "baz);

Now I need to take a shower :)

Heptahedron answered 10/9, 2008 at 19:12 Comment(0)
L
1

is it possible to write a function in a way where invalid arguments or non existent variables can be passed in and php will not error without the use of '@'

Yes you can!

porneL is correct [edit:I don't have enough points to link to his answer or vote it up, but it's on this page]

He is also correct when he cautions "But I recommend against abusing this for hiding programming errors." however error suppression via the Error Control Operator (@) should also be avoided for this same reason.

I'm new to Stack Overflow, but I hope it's not common for an incorrect answer to be ranked the highest on a page while the correct answer receives no votes. :(

Lockett answered 19/5, 2009 at 20:9 Comment(1)
I now have enough points to link straight to porneL's answer: https://mcmap.net/q/1045808/-php-function-argument-error-suppression-empty-isset-emulation#answer-311954 It's good to see that over time things start to turn around on a stackoverflow thread, with points eventually being appropriated to the correct person. :) It's just a shame that this thread has already been viewed 753 times and of thos people probably missed porneL's post (which was right at the bottom with zero votes) and instead saw the incorrect answer.Lockett
P
0

@Brian: I use a trinary operation to do the check for me:

return $value ? $value : $default;

this returns either $value OR $default. Depending upon the value of $value. If it is 0, false, empty or anything similar the value in $default will be returned.

I'm more going for the challenge to emulate functions like empty() and isset()

Purcell answered 10/9, 2008 at 19:18 Comment(0)
P
0

I'm sure there could be a great discussion on ternary operators vrs function calls. But the point of this question was to see if we can create a function that won't throw an error if a non existent value is passed in without using the '@'

Purcell answered 10/9, 2008 at 19:33 Comment(0)
C
0

@Sean That was already answered by Brian

return isset($input) ? $input : $default;
Chronological answered 10/9, 2008 at 19:46 Comment(1)
but within the function the error will have already fired yes?Purcell
E
0

Sean, you could do:

$result = ($func_result = doLargeIntenseFunction()) ? $func_result : 'no result';

EDIT:

I'm sure there could be a great discussion on ternary operators vrs function calls. But the point of this question was to see if we can create a function that won't throw an error if a non existent value is passed in without using the '@'

And I told you, check it with isset(). A ternary conditional's first part doesn't check null or not null, it checks true or false. If you try to check true or false on a null value in PHP, you get these warnings. isset() checks whether a variable or expression returns a null value or not, and it returns a boolean, which can be evaluated by the first part of your ternary without any errors.

Edo answered 10/9, 2008 at 19:49 Comment(0)
A
0

While the answer to the original question is "no", there is an options no one has mentioned.

When you use the @ sign, all PHP is doing is overriding the error_reporting level and temporarily setting it to zero. You can use "ini_restore('error_reporting');" to set it back to whatever it was before the @ was used.

This was useful to me in the situation where I wanted to write a convenience function to check and see if a variable was set, and had some other properties as well, otherwise, return a default value. But, sending an unset variable through caused a PHP notice, so I used the @ to suppress that, but then set error_reporting back to the original value inside the function.

Something like:

$var = @foo($bar);

function foo($test_var)
{
     ini_restore('error_reporting');

     if(is_set($test_var) && strlen($test_var))
     {
          return $test_var;
     }
     else
     {
          return -1;
     }
}

So, in the case above, if $bar is not set, I won't get an error when I call foo() with a non-existent variable. However, I will get an error from within the function where I mistakenly typed is_set instead of isset.

This could be a useful option covering what the original question was asking in spirit, if not in actual fact.

Activator answered 2/2, 2009 at 19:9 Comment(0)
N
0

If you simply add a default value to the parameter, you can skip it when calling the function. For example:

function empty($paramName = ""){
    if(isset($paramName){
        //Code here
    }
    else if(empty($paramName)){
        //Code here
    }
}
Nalley answered 31/5, 2009 at 7:34 Comment(0)
M
0

With a single line, you can acomplish it: myHappyFunction($someBogusVar="");

I hope this is what you are looking for. If you read the php documentation, under default argument values, you can see that assigning a default value to an function's argument helps you prevent an error message when using functions.

In this example you can see the difference of using a default argument and it's advantages:

PHP code:

<?php
function test1($argument)
{
    echo $argument;
    echo "\n";
}

function test2($argument="")
{
    echo $argument;
    echo "\n";
}

test1();
test1("Hello");
test1($argument);
$argument = "Hello world";
test1($argument);

test2();
test2("Hello");
test2($argument);
$argument = "Hello world";
test2($argument);
?>

Output for test1() lines:

Warning: Missing argument 1 for test1() .
Hello.
.
Hello world.

Output for test2() lines:

.
Hello.

Hello world.

This can also be used in combination to isset() and other functions to accomplish what you want.

Mayorga answered 5/6, 2012 at 0:55 Comment(0)
C
-1

And going further up the abstraction tree, what are you using this for?

You could either initialize those values in each class as appropriate or create a specific class containing all the default values and attributes, like:

class Configuration {

    private var $configValues = array( 'cool' => 'Defaultcoolval' ,
                                       'uncool' => 'Defuncoolval'  );

    public setCool($val) {
        $this->configValues['cool'] = $val;
    }

    public getCool() {
        return $this->configValues['cool'];
    }

}

The idea being that, when using defaultValue function everywhere up and down in your code, it will become a maintenance nightmare whenever you have to change a value, looking for all the places where you've put a defaultValue call. And it'll also probably lead you to repeat yourself, violating DRY.

Whereas this is a single place to store all those default values. You might be tempted to avoid creating those setters and getters, but they also help in maintenance, in case it becomse pertinent to do some modification of outputs or validation of inputs.

Chronological answered 10/9, 2008 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.