PHP suppress errors in function parameters - php

Extension from https://stackoverflow.com/a/55191/547210
I am creating a validating function to check several attributes of string variables, which may or may not have been set. (One of the attributes which is checked)
What I am trying to do with the function is receive arguments an unknown number of arguments in the form (See below), and suppress errors that may be caused by passing an unset variable.
I'm receiving the variables like validate([ mixed $... ] ) by using func_get_args()
The previous post mentioned that it was possible by passing by reference, now is this possible when the variables are passed implicitly like this?

If you pass a variable that is not set in the calling scope, the array returned by func_get_args() will contain a NULL value at the position where the variable was passed, and an error will be triggered. This error is not triggered in the function code itself, but in the function call. There is, therefore, nothing that can be done to suppress this error from within the code of the function.
Consider this:
function accepts_some_args () {
$args = func_get_args();
var_dump($args);
}
$myVar = 'value';
accepts_some_args($notSet, $myVar);
/*
Ouput:
Notice: Undefined variable: notSet in...
array(2) {
[0]=>
NULL
[1]=>
string(5) "value"
}
*/
As you can see, the variable name notSet appears in the error, telling us that the error was triggered in the caller's scope, not that of the callee.
If we want to counter the error, we could do this:
accepts_some_args(#$notSet, $myVar);
...and prefix the variable names with the evil # operator, but a better solution would be to structure our code differently, so we can do the checks ourselves:
function accepts_some_args ($args) {
var_dump($args);
}
$myVar = 'value';
$toPassToFunction = array();
$toPassToFunction[] = (isset($notSet)) ? $notSet : NULL;
$toPassToFunction[] = (isset($myVar)) ? $myVar : NULL;
accepts_some_args($toPassToFunction);
/*
Ouput:
array(2) {
[0]=>
NULL
[1]=>
string(5) "value"
}
*/

Related

How does php behave on initialized parameters?

Lets assume I have the following function:
function myTest($param = false){
echo $param;
}
And now I have the following call to the function
myTest($test);
However, $test wasnt declared yet by the moment the call is made. Will php throw an error?
I ask because I have a process where it is possible that some variables aren't instantiated before the call where they are used is made. In theory, this is okay, because I have a default behavior inside these functions handling this case (thats why Im initializing the functions parameter). However, if php throws an error in this case, then I have to build a workaround (which will be ugly ^^), but before doing so, I wanted to ask you :D
You don't get an error, but a warning. See variable basics.
It is not necessary to initialize variables in PHP however it is a very good practice. Uninitialized variables have a default value of their type depending on the context in which they are used - booleans default to FALSE, integers and floats default to zero, strings (e.g. used in echo) are set as an empty string and arrays become to an empty array.
Example: Default values of uninitialized variables
<?php
// Unset AND unreferenced (no use context) variable; outputs NULL
var_dump($unset_var);
// Boolean usage; outputs 'false' (See ternary operators for more on this syntax)
echo($unset_bool ? "true\n" : "false\n");
// String usage; outputs 'string(3) "abc"'
$unset_str .= 'abc';
var_dump($unset_str);
// Integer usage; outputs 'int(25)'
$unset_int += 25; // 0 + 25 => 25
var_dump($unset_int);
// Float/double usage; outputs 'float(1.25)'
$unset_float += 1.25;
var_dump($unset_float);
// Array usage; outputs array(1) { [3]=> string(3) "def" }
$unset_arr[3] = "def"; // array() + array(3 => "def") => array(3 => "def")
var_dump($unset_arr);
// Object usage; creates new stdClass object (see http://www.php.net/manual/en/reserved.classes.php)
// Outputs: object(stdClass)#1 (1) { ["foo"]=> string(3) "bar" }
$unset_obj->foo = 'bar';
var_dump($unset_obj);
?>

unset property in function also affecting passed variable

I have the following code
<?php
$foo[0] = new stdclass();
$foo[0]->foo = 'bar';
$foo[0]->foo2 = 'bar';
destroy_foo($foo);
var_dump ($foo);
function destroy_foo($foo)
{
unset($foo[0]->foo);
}
?>
The output is
array(1) { [0]=> object(stdClass)#1 (1) { ["foo2"]=> string(3) "bar" } }
I would expect $foo[0]->foo to still exist outside the function, but it doesn't. If I remove the properties and just use an array instead, it works. If I change the variable name inside the function, same problem. How can I use properties but make it work as expected?
What you see as an error is a PHP behaviour that's "working as expected": see the objects and references official guide.
It's not clear what you want to achieve with your code, but you should try to pass a clone of your object to the function.
In PHP Objects will only free their resources and trigger their __destruct method when all references are unsetted. So, to achieve your desire result, you have to
assign null insteadof unsetting it.
$foo[0]->foo = null;

Pass by reference in function for isset() & empty()

Basically I wanted to avoid doing something like this:
if((isset($var_1) && !empty($var_1)) || (isset($var_2) && !empty($var_2)) ...) { ....
So I created a function to try and solve it:
function set($item) {
return (isset($item) && !empty($item));
}
When passing in a variable that isn't set, take for example this:
$args = ['derp'];
if(set($args[0]) || $args[1]) {....
I get a thrown Notice stating that "Offset 1 isn't set, but when I change the function to note $item by-reference, it drops the PHP Notice:
function set(&$item) {
return (isset($item) && !empty($item));
}
Here is a demo
My question is this - how is this working? Is it because it's referencing the original $args array? Am I going insane?
When a function takes a by-reference argument, warnings about it being undefined are disabled at the time of the call. This is because the function might be used to assign the variable, so it's not an error to pass an undefined variable, or nonexistent index. For instance, suppose you had a function like:
function setTo3 (&$arg) {
$arg = 3;
}
setTo3($array[1]);
There's no reason to warn about $array[1] not being defined, because setTo3() never uses the argument's value.

PHP OOP and Arrays

I am new to PHP OOP and I am having problem getting arrays back.
class example
{
public $array;
public function __construct()
{
$this->array = array();
}
public function do_work()
{
$this->array[] = 'test';
}
}
$test = new example();
$test->do_work();
$test->array;
I keep getting a empty array instead of 'test'.
What am I doing wrong?
This is because you never actually call the function $test->do_work(); The constructor just creates the empty array, and then you attempt to access the property. It should be empty.
Updates
I see you updated your question. If you simply echo $test->array, it should just print Array. However, when I copy your updated code and perform a var_dump($test->array), this is the output I get:
array(1) { [0]=> string(4) "test" }
Which I believe is what you are expecting. The code that you have in your question, though, should output nothing. You are doing nothing with $test->array, the variable is being evaluated and then thrown away.
Your last statement, $test->array; doesn't actually do anything. My guess is that you are using something like echo. Your code should output the array if you use for example var_dump, see the example on codepad

Avoid duplicate code in statements like: isset($_GET['foo']['bar']) ? $_GET['foo']['bar'] : NULL;

To read unknown variables in PHP often I use code like the following:
$bar = isset($_GET['foo']['bar']) ? $_GET['foo']['bar'] : NULL;
I don't like to write the variable name twice. It just looks ugly and is too long for such an everyday task.
Do you know a better solution? Just using the # operator or suppress notices at all is no option (bad practice, slow).
With a custom function and variable by reference it is somehow possible:
function ifset(&$value)
{
if(isset($value)) return $value;
}
$bar = ifset($_GET['foo']['bar']); // $_GET is empty
However this creates silently new unwanted variables with that name/path. A var_dump($_GET) would print:
array(1) {
["foo"]=>
array(1) {
["bar"]=>
NULL
}
}
Although this will not completely solve your problem, in some cases you can use extract($_GET);
<?php
/* Suppose that $var_array is an array returned from
wddx_deserialize */
$size = "large";
$var_array = array("color" => "blue",
"size" => "medium",
"shape" => "sphere");
extract($var_array, EXTR_PREFIX_SAME, "wddx");
echo "$color, $size, $shape, $wddx_size\n";
?>
Use : "eval(foo,bar") see in a php manual for: eval.
Another way to redesign your function would be to make a recursive function that adds all of the set keys into an array as names and then simply check using in_array() function. If found, return value.
Finally PHP7 brings a solution. Yeah! The coalesce operator.
$bar = $_GET['foo']['bar'] ?? NULL;
If the value before the ?? exists and is not NULL it returns that one, otherwise it takes the fallback value from behind the ??. I love it!

Categories