PHP: variable interpolation issue - php

I am having a real issue with variable interpolation - maybe what I'm trying to do shouldn't be done? Sample code (IRL, the array is 70+ elements):
<form submit>
$_POST['A']; //returns 12
$_POST['B']; //returns 8
<query to get orig field values>
$OrigA = $row->appA; //returns 12
$OrigB = $row->appB; //return 14
<array of names>
$fields = array ("A", "B");
$querystr = "INSERT INTO tblEditHist VALUES ";
foreach ($fields as $field) {
$orig = "Orig" . $field;
$new = "\$_POST['app" . $field . "']";
$fieldname = "app" . $field;
if (${$orig} != ${$new}) { $querystr .= "('default', $applID, '$fieldname', '${$orig}', '${$new}', '$DateTimeReq', '$hvid'), "; };
}
print "querystr: " . $querystr . "\n";
The part if (${$orig} != ${$new}) is what's not working as I would expect. When I print it out to screen with print "DEBUG: if (${$orig} != ${$new}) { $querystr .= \"('default', $applID, '$fieldname', '{$orig}', '{$new}', '$DateTimeReq', '$hvid')\"; };<br />\n";, I see my variables aren't interpolating properly, my debug print says: DEBUG: if ( != ) { .... It should interpolate to (for B): DEBUG: if (8 != 14) { ...
I have tried various combinations of dollar signs and braces, but I don't seem to be making headway. Am I barking up the wrong tree here?
Thanks as always!!

Like this : No interpolation POST variable
<?php
$A = $_POST['A'] = 12; //returns 12
$B = $_POST['B'] = 8; //returns 8
$OrigA = 12; //returns 12
$OrigB = 14; //return 14
$fields = array ("A", "B");
$querystr = "INSERT INTO tblEditHist VALUES ";
foreach ($fields as $field) {
$orig = "Orig" . $field;
$fieldname = "app" . $field;
if (${$orig} != ${$field}) { $querystr .= "('default', $applID, '$fieldname', '${$orig}', '${$new}', '$DateTimeReq', '$hvid'), "; };
}
print "querystr: " . $querystr . "\n";
?>
See http://codepad.org/Ecro0PyG

I don't get all your questions but maybe this code could help you a little (you can use your $_POST var instead of mine $post, that is just to show result and debug):
$post = array();
$post['A'] = 12;
$post['B'] = 8;
$OrigA = 12;
$OrigB = 14;
$fields = array ("A", "B");
$querystr = "INSERT INTO tblEditHist VALUES ";
foreach ($fields as $field) {
$origVarName = 'Orig'.$field;
echo '$$origVarName = '.$$origVarName.'<br/>';
echo '$post[$field] = '.$post[$field].'<br/>';
$fieldname = "app" . $field;
if ($$origVarName != $post[$field]) {
echo $field.' NOT EQUAL!';
} else {
echo $field.' EQUAL!';
}
}

Related

Split results into variables after mysqli query

I have following:
if($broj_podstanica != "" && $broj_podstanica != 0) {
$uzmi_podstanice = "SELECT * FROM objekt WHERE vrsta_objekta = '2' ORDER BY sifra ASC LIMIT $broj_podstanica";
$pronasao_sve_podstanice = $db->query($uzmi_podstanice);
while($sifrePodstanica = $pronasao_sve_podstanice->fetch_assoc()) {
$sifreIzbrojane = $sifrePodstanica['sifra'] . ",";
$izbaci_zarez = explode(",", $sifreIzbrojane);
if (!isset($izbaci_zarez[0])) {
$izbaci_zarez[0] = "";
$pods0 = "";
} else {
$pods0 = $izbaci_zarez[0];
}
if (!isset($izbaci_zarez[1])) {
$izbaci_zarez[1] = "";
$pods1 = "";
} else {
$pods1 = $izbaci_zarez[1];
}
if (!isset($izbaci_zarez[2])) {
$izbaci_zarez[2] = "";
$pods2 = "";
} else {
$pods2 = $izbaci_zarez[2];
}
}
echo "1:" . $pods0;
echo "2:" . $pods1;
echo "3:" . $pods2;
echo "4:" . $pods3;
echo "5:" . $pods4;
}
Query gives me results: 30313233.
After while loop I tried to control variables $pods0, $pods1, $pods2, $pods3 and $pods4 but It gives me result for first variable only; $pods0 is 30..
Is it possible to get other values from variables?
You have some problems with your code, first of all, you do not need use isset() function, it always returns true because of the variable is exists. Secondly, if $izbaci_zarez[1] is empty you do not need to set it again with an empty value. The last thing, store the data in an array instead of a variable and it will not limit your variables count (Because of it will hard to follow) and set the values to their correct index.
if($broj_podstanica != "" && $broj_podstanica != 0) {
$uzmi_podstanice = "SELECT * FROM objekt WHERE vrsta_objekta = '2' ORDER BY sifra ASC LIMIT $broj_podstanica";
$pronasao_sve_podstanice = $db->query($uzmi_podstanice);
$i = 1;
$pods = array();
while($sifrePodstanica = $pronasao_sve_podstanice->fetch_assoc()) {
$sifreIzbrojane = $sifrePodstanica['sifra'] . ",";
$izbaci_zarez = explode(",", $sifreIzbrojane);
$pods[$i] = $izbaci_zarez[0];
$i++;
}
echo "1:" . $pods[1];
echo "2:" . $pods[2];
echo "3:" . $pods[3];
echo "4:" . $pods[4];
echo "5:" . $pods[5];
// and etc...
}

php foreach does not take all values from array

I'm making a json string which only contains the values which are entered in the form. so far it's going good but the only problem is that the foreach function which makes the string does not take all items from array.
Let's explain something and show my code:
if the $title is not empty I want my final ($content1) string to start with that value. Because it has some other quotes and curlybraces than other values. the same with the date field I also made an if for that because it also contains "date" in it. See my code below:
$title = "fiat titel";
$engine = "1.8";
$day = "1";
$month = "2";
$year = "1999";
$dateBuild = "02/02/1999";
// assoc array push function
function array_push_assoc($array, $key, $value){
$array[$key] = $value;
return $array;
}
$array = array();
if(!empty($title)) {
$array = array_push_assoc($array, 'title', $title);
}
if(!empty($color)) {
$array = array_push_assoc($array, 'field_modelcolor', $color);
}
if(!empty($model)) {
$array = array_push_assoc($array, 'field_carmodel', $model);
}
if(!empty($engine)) {
$array = array_push_assoc($array, 'field_modelengine', $engine);
}
if(!empty($fuel)) {
$array = array_push_assoc($array, 'field_modelfuel', $fuel);
}
if(!empty($day) && !empty($month) && !empty($year)) {
$array = array_push_assoc($array, 'field_modelyear', $dateBuild);
}
$content1 = "";
foreach($array as $ftitle => $value) {
if(empty($content1) && !empty($title)) {
$content1 = ',"' . $ftitle . '":"' . $value . '"';
}
if(!empty($day) && !empty($month) && !empty($year)) {
$content1 = ',"' . $ftitle . '":{"und":[{"value":{"date":"' . $value . '"}}]}';
}
$content1 = ',"' . $ftitle . '":{"und"[{"value":"' . $value . '"}]}';
}
$postContent = '{"type":"carmodels"' . $content1 . '}';
var_dump($array);
echo $postContent;
Right now it's only echo'ing:
{"type":"carmodels","field_modelyear":{"und"[{"value":"02/02/1999"}]}}
And it should be (example):
{"type":"carmodels","field_modelyear":{"und":[{"value":{"date":"02/02/1999"}}]},"field_modelengine":{"und"[{"value":"1.6"}]}}
Thanks in advance!

How to sort an array-like variable?

I am adding the names of regions to a a variable using the below code (shortened). Everything works as intended, except for the sort function which throws an error saying that it requires an array instead of a string.
How can I still manage to sort the content of my variable alphabetically ?
$regions = '';
$countR = 1;
foreach ($objR->days as $days) {
if($days->dateMatch == "Yes" && !empty($days->regions)) {
foreach(explode(',', $days->regions) as $r){
$regions .= str_replace(" / ", ", ", $r)) . "<br />";
$countR++;
}
}
}
sort($regions);
Try this:
You should use array for storage.
$regions = array();
$countR = 1;
foreach ($objR->days as $days) {
if($days->dateMatch == "Yes" && !empty($days->regions)) {
foreach(explode(',', $days->regions) as $r){
$region = str_replace(" / ", ", ", $r)) . "<br />";
array_push($regions,$region);
$countR++;
}
}
}
sort($regions);

Multi dimensional array. What am I doing wrong?

I have a function:
function getDecision($num_players, $decisionType, $stage){
echo "in the function 1: ".$num_players."<br/>";
echo "in the function 2: ".$decisionType."<br/>";
echo "in the function 3: ".$stage."<br/>";
$x = mysql_query("
SELECT `decisionValue` FROM `teamdecision` WHERE `decisionType` = '$decisionType' && `period`= '$stage'
")or die($x."<br/><br/>".mysql_error());
$y = array();
$i="0";
while ($i<($num_players) && $row = mysql_fetch_assoc($x))
{
$y[$i] = $row['decisionValue'];
$i++;
}
return ($y);
}
Y will be populated with a number of values depending on the $num_players. I am calling the function as follows:
$value = array();
$name = array();
for ($j=0;$j<$num_players;$j++){
for ($i=0;$i<4;$i++){
$name[0] = "SUconsultant";
$name[1] = "marketT";
$name[2] = "sector";
$name[3] = "saleprice";
echo $name[$i]."<br/>";
$value[$i] = getDecision($num_players, $name[$i], $currentStage)."<br/>";
echo "Value = ".$value[$j][$i]."<br/>";
}
}
As you can see I am doing this wrong. I need to output the data located in $value however I am confused with how multi dimensional arrays work. I understand I need to read up on the subject, if possible can you point me to a suitable learning source?
So I changed up the code so that the following is being used to produce an output below:
$value = array();
$name = array();
for ($j=0;$j<$num_players;$j++){
for ($i=0;$i<4;$i++){
$name[0] = "SUconsultant";
$name[1] = "marketT";
$name[2] = "sector";
$name[3] = "saleprice";
echo $name[$i]."<br/>";
$value[$i] = getDecision($num_players, $name[$i], $currentStage)."<br/>";
echo "Value = ".$value[$j][$i]."<br/>";
}
}
I expected to output as follows:
$value[0] should contain $y which then contains each SUconsultant value. $value[1] should contain $y which then contains each marketT value and so on.
for ($i=0;$j<4;$i++){
should be
for ($j=0;$j<4;$j++){
And
$value[$i] = getDecision($num_players, $name[$i], $currentStage)."<br/>";
should be
$value[$j] = getDecision($num_players, $name[$j], $currentStage)."<br/>";
You have a $j in your first for loop, but setting and incrimenting $i in it. Maybe change them to $j as well.
EDIT
It actually looks like you have an issue with where you are returning the data:
echo "Value = ".$value[$j][$i]."<br/>";
This should be (it appears):
for ($f = 0; $f < $num_players; $f++){
echo "Value = ".$value[$i][$f]."<br/>";
}
Since you are currently on $value[$i] by the time you reach this point, then you need it to echo out one for each player.
This solution worked, after a lot of playing around it seems that the [] after of
the value array was also needed? At least I think so
$value = array();
$name = array();
for ($j=0;$j<$num_players;$j++){
for ($i=0;$i<4;$i++){
$name[0] = "SUconsultant";
$name[1] = "marketT";
$name[2] = "sector";
$name[3] = "saleprice";
echo $name[$i]."<br/>";
$value[] = getDecision($num_players, $name[$i], $currentStage);
//echo "Value = ".$value[$i]."<br/>";
echo "<br/><hr/>";
echo "Value = ".$value[$i][$j]."<br/><hr/>";
}
}
Output:
And now I have changed to:
$value[] = getDecision($num_players, $name[$i], $currentStage);
echo "Team ".$j." ".$name[$i]." = ".$value[$i][$j]."<br/>";
To get my eventual goal of:

Walk array recursively and print the path of the walk

Can someone help me with some code or instructions on how to walk recursively an array and when reaching the last element print the full path to it? A simple echo will work because I will adapt the code to some other function I'm developing.
The function doesn't need to figure the array dimension because this param will be passed:
Example:
$depth = 8;
$array[1][3][5][6][9][5][8][9];
When function reachs the 8th element it print all the path to it:
//print path
'1 -> 3 -> 5 -> 6 -> 9 -> 5 -> 8 -> 9'
As I said, only printing in this format will work cause I will implement the code into some other function.
array keys can have the same value. Obviously not the same value in the same sequence for the entire arary.
Updated:
Walk recursively function:
$someArray[1][2][3] = 'end';
$someArray[1][2][6] = 'end';
$someArray[1][3][6] = 'end';
$someArray[4][3][7] = 'end';
function listArrayRecursive(&$array_name, $ident = 0){
if (is_array($array_name)){
foreach ($array_name as $k => &$v){
if (is_array($v)){
for ($i=0; $i < $ident * 10; $i++){ echo " "; }
echo $k . " : " . "<br>";
listArrayRecursive($v, $ident + 1);
}else{
for ($i=0; $i < $ident * 10; $i++){ echo " "; }
echo $k . " : " . $v . "<br>";
}
}
}else{
echo "Variable = " . $array_name;
}
}
listArrayRecursive($someArray);
Will print:
1 :
2 :
3 : end
6 : end
3 :
6 : end
4 :
3 :
7 : end
Now, how can I also print the path of the array everytime it reaches the end? For example:
1 :
2 :
3 : end : path -> 1,2,3
6 : end : path -> 1,2,6
3 :
6 : end : path -> 1,3,6
4 :
3 :
7 : end : path -> 4,3,7
EDITED CODE ADDING A THIRD PARAM TO RECORD THE PATH:
$someArray[1][2][3] = 'end';
$someArray[1][2][6] = 'end';
$someArray[1][3][6] = 'end';
$someArray[4][3][7] = 'end';
$someArray[3][2] = 'end';
function listArrayRecursive(&$array_name, $ident = 0, $path = null){
foreach ($array_name as $k => &$v){
if (is_array($v)){
for ($i=0; $i < $ident * 10; $i++){ echo " "; }
echo $k . " : " . "<br>";
$path .= $k . ', ';
listArrayRecursive($v, $ident + 1, $path);
}else{
for ($i=0; $i < $ident * 10; $i++){ echo " "; }
echo $k . " : " . $v . ' - path -> ' . $path . "<br>";
}
}
}
listArrayRecursive($someArray);
Will print:
1 :
2 :
3 : end - path -> 1, 2,
6 : end - path -> 1, 2,
3 :
6 : end - path -> 1, 2, 3,
4 :
3 :
7 : end - path -> 1, 4, 3,
3 :
2 : end - path -> 1, 4, 3,
You could employ a RecursiveIteratorIterator (docs) to take the hard work out of recursing through the arrays.
function listArrayRecursive($someArray) {
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($someArray), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $k => $v) {
$indent = str_repeat(' ', 10 * $iterator->getDepth());
// Not at end: show key only
if ($iterator->hasChildren()) {
echo "$indent$k :<br>";
// At end: show key, value and path
} else {
for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) {
$p[] = $iterator->getSubIterator($i)->key();
}
$path = implode(',', $p);
echo "$indent$k : $v : path -> $path<br>";
}
}
}
This example is to give you idea, not to solve the actual task.
function recursiveSearch($array,$search){
foreach($array as $key=>$val){
if($val==$search)return $key;
$x=recursiveSearch($array[$key],$search);
if($x)return $key.' -> '.$x;
}
}
echo recursiveSearch($array,'search');
If no match is found, null is returned.
$a= array(1,2,3,4,5,6);
$val = end($a);
print_array($a,$val);
function print_array(&$arr, $val)
{
if ($val === false)
return;
$curr = prev($arr);
print_array($arr,$curr);
echo $val;
}
I just wrote a function that makes recursive looping a bit easier:
Similar to array_walk_recursive but with some extra functionality
public static function walk($array, $callback, $custom = null, $recursive = false, $info = [])
{
$r = $recursive;
if (gettype($r) === 'integer') {
$r--;
}
$info['depth'] = empty($info)?1:$info['depth'] + 1;
$info['count'] = count($array);
$info['i'] = 1;
foreach($array as $k => $v) {
if (is_array($v) && $r > 0) {
$array[$k] = static::walk($v, $callback, $custom, $r, $info);
} else {
$array[$k] = $callback($v, $k, $custom, $info);
}
$info['i'] ++;
}
return $array;
}
public static function walkable($v, $k, $custom, $info)
{
if (is_string($v)) {
return $v." [ custom: {$custom['key']} ] [ level: ".$info['depth'].' | No '.$info['i'].' of '.$info['count']." ]";
}
return $v;
}
Called like so:
$result = Namespace\ClassName::walk($array, ['Namespace\ClassName', 'walkable'], ['key'=>'value'], true);
Setting recursive to false will only evaluate the first level.
Setting recursive to true will cause it to traverse the entire array.
Setting recursive to an integer will cause it to only traverse to that depth.
Walkable functions can be referenced or passed to callback as anonymous function.
(expects: value, key, custom, info)
The returned value replace the current value.
Custom data can be passed and some additional info is provided for you.
You can expand on the walk function if you need additional info.
I had similar problem. Here is a Depth-First Search-ish solution(no path depth included, it reaches until the very end of the array). Comment the 'if' statement if u don't want to include the value:
$output = array();
retrievePath($someArray, $output);
function retrievePath($someArray, array &$pathKeeper)
{
if(!is_array($someArray)){ // $someArray == "end"
$element = array_pop($pathKeeper) ?? '';// if the array is empty pop returns null, we don't want that
array_push($pathKeeper, $element . '->'. $someArray);
} else{
end($someArray);//we want to get the last element from the array so we move the internal pointer to it's end
$endElKey = key($someArray);//take the key where the pointer is
reset($someArray);
foreach($someArray as $key=>$value){
$element = array_pop($pathKeeper);
array_push($pathKeeper, $element === null ? $key : $element . '->' . $key);// we don't want '->' at the beginning
retrievePath($value, $pathKeeper);
if($key != $endElKey) //we check whether this is not the last loop
array_push($pathKeeper, $element);
}
}
}
<?php
function printListRecursive($a, $var='', $i = 0) {
if (!is_array($a)) {
$var .= $a;
return $var;
}
$string = "";
foreach ($a as $k => $value) {
$string .= str_repeat(" ", $i) .' - '. $k . ':';
if (!is_array($value)) {
$string .= $value . '<br />';
} else {
$string .= '<br />';
$string .= printListRecursive($value, $var, $i + 1);
}
}
return $string;
}
$test_array = [
'America' => [
'Argentina' => 'Buenos Aires',
'Peru' => 'Lima'
],
'Europe' => [
'Ireland' => 'Dublin',
'France' => 'Paris',
'Italy' => 'Rome'
]
];
$result = printListRecursive($test_array);
echo $result;
?>
Check code here
I came up with the following function based on #salathe's one. It returns an array where each element is an array containing the leaf at index 0 and the array of the path keys at index 1:
function loosenMultiDimensionalArrayPathForEachVal($array) {
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array), \RecursiveIteratorIterator::SELF_FIRST);
$iterator->rewind();
$res = [];
foreach ($iterator as $v) {
$depth = $iterator->getDepth();
for ($path = array(), $i = 0, $z = $depth; $i <= $z; $i++) {
$path[] = $iterator->getSubIterator($i)->key();
}
$leaf = $array;
foreach ($path as $pathKey) {
$leaf = $leaf[$pathKey];
}
if (!is_array($leaf)) {
$res[] = [
$v,
$path
];
}
}
return $res;
}
The main reason I implemented this one is that $iterator->hasChildren() returns true if the current iterated leaf is an object. Therefore, I wouldn't be able to get the path of it that way.
I found this solution, which also keeps into account if elements of the structure are arrays:
$file_contents=file_get_contents("data.json");
$json_dump=json_decode($file_contents);
printPath($json_dump, '', "" ,"");
function printPath($the_array, $path, $prevType) {
// Parse all elements of a structure
// and print full PHP path to each one.
foreach($the_array as $key => $value) {
if(is_array($value)) {
// Array element cannot be directly printed: process its items as objects:
printPath($value, $path . $key , "array");
} else {
if (!is_object($value)) { // If the element is not an object, it can be printed (it's a leaf)
if(is_string($value)) {
$finalValue = '"' . $value . '"';
} else {
$finalValue = $value;
}
if($prevType == "array") {
// If array element, add index in square brackets
echo($path . "[" . $key . "] = " . $finalValue . "<br>");
} else {
echo($path . $key . " = " . $finalValue . "<br>");
}
} else { // else store partial path and iterate:
if($prevType == "array") {
// Path of array element must contain element index:
printPath($value, $path . "[" . $key . "]->" , "dummy");
} else {
printPath($value, $path . $key . "->", "dummy");
}
}
}
}
}
Example output:
status->connections->DSS-25->band = "X"
status->connections->DSS-25->endAt = "2019-11-20T20:40:00.000Z"
status->connections->DSS-25->startAt = "2019-11-20T12:40:00.000Z"
geometry[0]->obs[0]->name = "UDSC64"
geometry[0]->obs[0]->hayabusa2->azm = 90.34
geometry[0]->obs[0]->hayabusa2->alt = -20.51
In case anybody is interested, here it is the port to Javascript:
function iterate(obj, stack, prevType) {
for (var property in obj) {
if ( Array.isArray(obj[property]) ) {
//console.log(property , "(L=" + obj[property].length + ") is an array with parent ", prevType, stack);
iterate(obj[property], stack + property , "array");
} else {
if ((typeof obj[property] != "string") && (typeof obj[property] != "number")) {
if(prevType == "array") {
//console.log(stack + "[" + property + "] is an object, item of " , prevType, stack);
iterate(obj[property], stack + "[" +property + "]." , "object");
} else {
//console.log(stack + property , "is " , typeof obj[property] , " with parent ", prevType, stack );
iterate(obj[property], stack + property + ".", "object");
}
} else {
if(prevType == "array") {
console.log(stack + "[" + property + "] = "+ obj[property]);
} else {
console.log(stack + property , " = " , obj[property] );
}
}
}
}
}
iterate(object, '', "File")
You can add a third parameter which holds the actual path as String. At the end you can output it then.

Categories