I have a multidimensional array produced by json_decode(). The json is dynamically generated, that means some keys will be present randomly.
I would like to avoid Undefined index: notice, so i encapsulated the calls to the array in a function like this:
function exists($value) {
if (isset($value)) {
return $value;
}
}
I then call data:
$something = exists($json_array['foo']['bar']['baz']);
But i still get the Undefined index: baz notice. Any suggestions?
It seems you are new to PHP, so I'll give a bit lengthier answer than normal.
$something = exists($json_array['foo']['bar']['baz']);
This is equivalent to what you wrote:
$baz = $json_array['foo']['bar']['baz'];
$something = exists($baz);
As you may have noticed, this means that $json_array['foo']['bar']['baz'] is evaluated before it's passed to exists(). This is where the undefined index is coming from.
The correct idiom would be more like this:
$something = NULL;
if (isset($json_array['foo']['bar']['baz'])) {
$something = $json_array['foo']['bar']['baz'];
}
The following is also identical to the above lines:
$something = isset($json_array['foo']['bar']['baz'])
? $json_array['foo']['bar']['baz']
: NULL;
You would have to chain the exists calls one by one, because you are trying to dereference the array before you send it to the exists function.
See this question for more info: Check if a "run-time" multidimensional array key exists
$json_array['foo']['bar']['baz'] fails when you pass it as an argument, before it's passed to isset(). That is your problem.
Related
I'm used to JavaScript where I often write things like this: const ref = obj.arr || (obj.arr = []);.
With one line of code, this gives me a reference on obj.arr after having initialized it to empty array if it didn't exist.
I'm trying to do the same in PHP but I'm struggling with ampersands, since the assignation is done by copy of value by default. Here is my failing attempt which I thought it would work:
$ref= &$obj['arr'] ?? &($obj['arr'] = []);
If I understand your question correctly, a ternary operator should suffice:
$obj['arr'] = isset($obj['arr']) ? $obj['arr'] : [];
$ref = &$obj['arr']);
I am trying to write a function to avoid getting variable undefined error. Right now, i have a code like this:
function check($str){
if(isset($str)){
$s = $str;
} else {
$s = "";
}
}
check($_GET['var']);
The get var is not set. I am getting a variable undefined error on my screen. How do i alter my function to not throw this error and just return "" if it is not set? I don't want to have to code 100 if statements to avoid getting variable undefined. Thanks.
We already have in PHP a construct to check that. It is called isset(). With it you can check whether a variable exists. If you would like to create it with some default values if it doesn't exist yet, we also have syntax for it. It's null-coalescing operator.
$_GET['var'] = $_GET['var'] ?? '';
// or since PHP 7.4
$_GET['var'] ??= '';
Although I'm not sure if it is the right way of doing it, for the sake of providing an answer you can pass the variable by reference, this allows you to get away with passing undefined variables and check if it is set inside the function..
function check(&$str){
if(!isset($str)){
$str = "not set";
}
}
check($_GET['var']);
echo $_GET['var'];
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.
If accessing an undefined index of a null reference, PHP does not throw any errors.
<?php
$array = &$foo['bar'];
if ($array['stuff']) echo 'Cool'; // No PHP notice
$array['thing'] = 1; // Array created; $foo['bar']['thing'] == 1
$array['stuff']; // PHP notice
If $array wasn't a reference PHP would have complained on the first line.
Why doesn't it for references? Do I need bother with isset for null references, or is PHP complaining internally and not letting me know?
In your code $array is null. The following code will not give you a notice either:
$b = null;
if ($b['stuff']) echo 'cool';
This is strange, this comment in the documentation points to that fact.
You must raise your error reporting level. Your example $array['stuff'] will throw warnings about index not found. I often combine a test for key in with the evaluation so as to prevent those warnings:
if( array_key_exists("blah",$arr) && strlen($arr['blah']) > 0 ) {
; // do stuff here
}
I often combine variables in with array names because anytime I have to cut-n-paste copy code to the next section to do the same-ish thing, I'd rather make an array of variable names and then iterate through the variable names. The most absurd condition is when I have billing and shipping data to manipulate, where I'll have an array variable name $BorS or just $BS and then at the top, set $BorS="shipping"; and end up with really interesting statements like:
${$BorS."data"}[${$BorS."_addr1"}]=$input_array[$BorS."_address_line_1"];
Why not just do:
$array = array();
I have the following structure:
$par4 = json_decode($source_code)->$par1->$par2->$par3;
$par5 = $par4[0]->attributes->attribute[1]->value;
where par1, par2 and par3 are strings. How do I chain the par4 and par5 on one line.
This does not work because of the array / object nesting I guess:
json_decode($source_code)->$par1->$par2->$par3[0]->attributes->attribute[1]->value;
Here's the error:
Undefined property: stdClass::$o
What about
$par5 = current(json_decode($source_code)->$par1->$par2->$par3)->attributes->attribute[1]->value;
This works if you are always need in the first (0th) value of the array.
You can also create a function that returns the nth-value:
function third_value($arr) { return $arr[2]; }
$par5 = third_value(json_decode($source_code)->$par1->$par2->$par3)->attributes->attribute[1]->value;
I'm not sure, what you really need but try using {} to highlight what you need
{json_decode($source_code)->$par1->$par2->$par3}[0] // I think this is right
json_decode($source_code)->$par1->$par2->${par3[0]}
json_decode($source_code)->$par1->$par2->{$par3[0]}