compact() not adding empty variables - php

Im trying to get a list of variables into an array (for an error reporting class), but if the variable is NOT set it is not being "compacted".
The below is extracts of the code:
$testVar1 = 123;
$testVar2 = 'ABC';
$ErrorArray = compact('testVar1', 'testVar2', 'notSetVar');
I then walk through the $ErrorArray with :
foreach($ErrorArray as $key => $value) {
$TempErrorMessage .= '$'.$key.' == '.$value.' ---- ';
}
The resulting output is :
$testVar1 == 123 ---- $testVar2 == ABC ----
The problem is, i would like to to output "notSetVar" as ""/NULL, as this is likely to be where my error is....
Any suggestions would be greatly welcomed!
Best Regards
Ford

According to PHP doc
http://php.net/manual/en/function.compact.php
compact creates an array containing variables and their values.
For each of these, compact() looks for a variable with that name in the current symbol table and adds it to the output array such that the variable name becomes the key and the contents of the variable become the value for that key. In short, it does the opposite of extract().
Any strings that are not set will simply be skipped.
So, it is not possible to pass variable via compact unless its set. My suggestion is, check variable before compact().
$testVar1 = 123;
$testVar2 = 'ABC';
if (!isset($notSetVar) {
$notSetVar = null;
}
$ErrorArray = compact('testVar1', 'testVar2', 'notSetVar');
var_dump($ErrorArray);

Related

php array syntax ${ is confusing me

I create a $values array and then extract the elements into local scope.
$values['status'.$i] = $newStatus[$i];
extract($values);
When I render an html page. I'm using the following
<?php if(${'status'.$i} == 'OUT'){ ?>
but am confused by what the ${ is doing and why $status.$i won't resolve
$status.$i means
take value of $status variable and concatenate it with value of $i variable.
${'status'.$i} means
take value of $i variable, append id to 'status' string and take value of a variable 'status'.$i
Example:
With $i equals '2' and $status equals 'someStatus':
$status.$i evaluated to 'someStatus' . '2', which is 'someStatus2'
${'status'.$i} evaluated to ${'status'.'2'} which is $status2. And if $status2 is defined variable - you will get some value.
I wanted to add to the accepted answer with a suggested alternate way of achieving your goal.
Re-iterating the accepted answer...
Let's assume the following,
$status1 = 'A status';
$status = 'foo';
$i = 1;
$var_name = 'status1';
and then,
echo $status1; // A status
echo $status.$i; // foo1
echo ${'status'.$i}; // A status
echo ${"status$i"}; // A status
echo ${$var_name}; // A status
The string inside the curly brackets is resolved first, effectively resulting in ${'status1'} which is the same as $status1. This is a variable variable.
Read about variable variables - http://php.net/manual/en/language.variables.variable.php
An alternative solution
Multidimensional arrays are probably an easier way to manage your data.
For example, instead of somthing like
$values['status'.$i] = $newStatus[$i];
how about
$values['status'][$i] = $newStatus[$i];
Now we can use the data like,
extract($values);
if($status[$i] == 'OUT'){
// do stuff
}
An alternative solution PLUS
You may even find that you can prepare your status array differently. I'm assuming you're using some sort of loop? If so, these are both equivalent,
for ($i=0; $i<count($newStatus); $i++){
$values['status'][$i] = $newStatus[$i];
}
and,
$values['status'] = $newStatus;
:)

Using citation marks around a variable in array access

I'm reading som legacy code and come over a curious case:
$my_assoc_array; /* User defined associative array */
$my_key; /* User defined String */
$value = $my_assoc_array["$my_key"];
Is there any clever reason why you would want to have citation marks (") around the variable when it's used as a key? Like a very special corner case? Or is there simply no reason at all to do this?
-- EDIT --
Maybe in some old version of PHP there was a difference? (Remember this is legacy code).
There is one example that I can find where the output differs which is when $mykey = false.
(which perhaps does not apply to your example where $mykey is a string, but then again: this is the wild wild world of PHP)
<?php
$arr = array("1"=>"b", "0"=>"a");
$mykey = false;
var_dump($arr[$mykey]);
// returns "a"
var_dump($arr["$mykey"]);
// gives Undefined index error
$mykey = true;
var_dump($arr[$mykey]);
// returns "b"
var_dump($arr["$mykey"]);
// returns "b"
What this can be (mis-)used for beats me...
Its not necessary to bind variable name with double quotes inside array index:
you can simply write with out quotes:
$value = $my_assoc_array[$my_key];
it will be different one if $my_key is an integer value
$my_key = 3; /* User defined String */
$value = $my_assoc_array["$my_key"]; /* returns $my_assoc_array["3"] */
$value = $my_assoc_array[$my_key]; /* returns $my_assoc_array[3] */

Add two $row together in one php echo

I'm not even sure if what I am trying to do is possible, I have a simple php echo line as below..
<?php echo $T1R[0]['Site']; ?>
This works well but I want to make the "1" in the $T1R to be fluid, is it possible to do something like ..
<?php echo $T + '$row_ColNumC['ColNaumNo']' + R[0]['Site']; ?>
Where the 1 is replaced with the content of ColNaumNo i.e. the returned result might be..
<?php echo $T32R[0]['Site']; ?>
It is possible in PHP. The concept is called "variable variables".
The idea is simple: you generate the variable name you want to use and store it in another variable:
$name = 'T'.$row_ColNumC['ColNaumNo'].'R';
Pay attention to the string concatenation operator. PHP uses a dot (.) for this, not the plus sign (+).
If the value of $row_ColNumc['ColNaumNo'] is 32 then the value stored in variable $name is 'T32R';
You can then prepend the variable $name with an extra $ to use it as the name of another variable (indirection). The code echo($$name); prints the content of variable $T32R (if any).
If the variable $T32R stores an array then the syntax $$name[0] is ambiguous and the parser needs a hint to interpret it. It is well explained in the documentation page (of the variable variables):
In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.
You can do like this
$T1R[0]['Site'] = "test";
$c = 1;
$a = "T".$c."R";
$b = $$a;
echo "<pre>";
print_r($b[0]['Site']);
Or more simpler like this
$T1R[0]['Site'] = "test";
$c = 1;
$a = "T".$c."R";
echo "<pre>";
print_r(${$a}[0]['Site']);

Dynamically created Variables in PHP produce occasionally names like "_GET" or "_POST" instead of the variable names

I have a function from which I call many different variables, and produce another (dynamically created) return variable.
All good. (I explain my Problem below this PHP 5.3 example)
function showArrayIntersection($ar1, $ar2) {
$dynamicName = array_search($ar1, $GLOBALS) . '_' . array_search($ar2, $GLOBALS);
global ${$dynamicName};
${$dynamicName} = implode(array_values(array_intersect($ar1, $ar2)));
}
$Bankers = [6,7,0,6,5,6,2]; // `[]` is equivalent to `array()` introduced in PHP 5.4
$Bond = [6,7,0,5,0];
$Politicians = [4,6,1,6,4,6,3];
$James = [0,1,0,3,7];
showArrayIntersection($James, $Bond);
showArrayIntersection($Bankers, $Politicians);
echo "Moneysystem: $Bankers_Politicians\n";
echo "Moneypenny : $James_Bond\n";
Output:
Moneysystem: 666
Moneypenny : 007
This works most of the time well, but sometimes only instead of a variable name like $James_Bond I get a variable name like POST_POST or GET_GET, meaning instead of the name James or Bond PHP returns either a "_GET" or a "_POST".
Since AbraCadaver asked full of solicitousness: "What in the world are you doing?"
here my solution and explanation:
Einacio: I coudn't create the names on the fly because the already arrive from a first function dynamically, so the actual variable name is not the true name.
And AbraCadaver pointed out that array_search() does not accept an array; unfortunately for sake of brevity I omitted that I pass on as a first argument not an array but another dynamic created variable from the root - I didn't want to make it too complicated, but basically it works like this:
function processUsers ($userName , $request2send ){
global ${$user.'_'.$request2send};
$url2send = "http...?request=".$request2send ;
...
$returnedValue = receivedDataArray ();//example elvis ([0] => Presley );
${$user.'_'.$request2send} = $returnedValue;
}
--- now Now I get the value of the function in the root ---
$firstValue = processUsers ("cuteAnimal" , "getName");
// returns: $cuteAnimal_getName = "Mouse"
and
$secondValue = processUsers ("actorRourke" , "getFirstName");
// returns: $actorRourke_getFirstName = "Mickey";
And now the bummer - a second function which needs the first one to be completed:
function combineValues ($firstValue , $secondValue ){
global ${$firstValue.'AND'.$secondValue};
${$firstValue.'_'.$secondValue} = $firstValue." ".$secondValue;
}
// returnes $actorRourke_getFirstNameANDcuteAnimal_getName = "Mickey Mouse";
Of course the second function is much more complicated and requires first to be completed,
but I hope you can understand now that it is not an array directly which I passed on but dynamic variable names which I could not just use as "firstValue" but I needed the name "actorRourke_getFirstName".
So AbraCadaver's suggestion to use $GLOBALS[..] did not work for me since it requires arrays.
However: Thanks for all your help and I hope I could now explain the issue to you.
Argument 1 for array_search() does not accept an array.
print_r($GLOBALS); will show the empty $_GET and $_POST arrays.
What in the world are you doing?
To go with Einacio:
function showArrayIntersection($ar1, $ar2) {
$GLOBALS[$ar1 . '_' . $ar2] = implode(array_intersect($GLOBALS[$ar1], $GLOBALS[$ar2]));
}
showArrayIntersection('James', 'Bond');
echo "Moneypenny : $James_Bond\n";
You could check to make sure they exist of course isset().
how about just using the names of the variables? it would also avoid value conflicts
function showArrayIntersection($ar1, $ar2) {
$dynamicName = $ar1 . '_' . $ar2;
global ${$dynamicName};
${$dynamicName} = implode(array_values(array_intersect($_GLOBALS[$ar1], $_GLOBALS[$ar2])));
}
$Bankers = [6,7,0,6,5,6,2]; // `[]` is equivalent to `array()` introduced in PHP 5.4
$Bond = [6,7,0,5,0];
$Politicians = [4,6,1,6,4,6,3];
$James = [0,1,0,3,7];
showArrayIntersection('James', 'Bond');
showArrayIntersection('Bankers', 'Politicians');
echo "Moneysystem: $Bankers_Politicians\n";
echo "Moneypenny : $James_Bond\n";

PHP variable variable name containing index

$arr[0]=123;
$a="arr[0]";
echo $$a;
gives me error
Notice: Undefined variable: arr[0]
on the last line.
What should I do to make it work?
EDIT:
Above is the simplification of what I want to do. If someone wants to know why I want to do this, then here's the explanation:
This is something like what I want to do:
if(condition){
$a=$arr1[0][0];
$b=$arr1[0][1];
$c=$arr1[0][2];
}
else{
$a=$arr2[0];
$b=$arr2[1];
$c=$arr2[2];
}
I can compact it like this:
if(condition)
$arr=$arr1[0];
else
$arr=$arr2;
$a=$arr[0];
$a=$arr[1];
$a=$arr[2];
But I wanted to try doing this using variable variable:
if(condition)
$arr="$arr1[0]";
else
$arr="$arr2";
$a={$$arr}[0];
$b={$$arr}[1];
$c={$$arr}[2];
Sure, we don't need variable variables as we can still code without them. I want to know, for learning PHP, why the code won't work.
Now that you said what you’re actually trying to accomplish: Your code doesn’t work because if you look at $arr1[0][0], only arr is the variable name; the [0] are special accessors for certain types like strings or arrays.
With variable variables you can only specify the name but not any accessor or other operation:
A variable variable takes the value of a variable and treats that as the name of a variable.
Your solution with the additional variable holding the array to access later on would be the best solution to your problem.
What you are trying to do just won't work - the code $arr[0] is referencing a variable called $arr, and then applying the array-access operator ([$key]) to get the element with key 0. There is no variable called $arr[0], so you cannot reference it with variable-variables any more than you could the expression $foo + 1 .
The real question is why you want to do this; variable variables are generally a sign of very messy code, and probably some poor choices of data structure. For instance, if you need to select one of a set of variables based on some input, you probably want a hash, and to look up an item using $hash[$item] or similar. If you need something more complex, a switch statement can often cover the cases you actually need.
If for some reason you really need to allow an arbitrary expression like $arr[0] as input and evaluate it at runtime, you could use eval(), but be very very careful of where the input is coming from, as this can be a very easy way of introducing security holes into your code.
FROM PHP DOC
In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.
Use
echo ${$a}[0]; // 123
Edit : Based on your edit you can simply have
list($a, $b, $c) = (condition) ? $arr1[0] : $arr2;
Or
$array = (condition) ? $arr1[0] : $arr2;
$a = $array[0];
$b = $array[1];
$c = $array[2];
As pointed out you don't need variable variables. To get a PHP variable variable name containing index (a key) use array_keys() or array_search() or other array parsers. From php's site:
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;
You could also use the following (using $var= instead of echo):
$arr[0]=123;
$arr[1]=456;
foreach ($arr as $key => $value) {
echo "arr[{$key}] = {$value} \r\n";
}
Which outputs:
arr[0] = 123
arr[1] = 456
But I don't see why you'd do that, since the whole point of the array is not doing that kind of stuff.

Categories