output of array always equals 'i' - php

I have the variable $request. If i do vardump($request), I get the output of:
array(7) {
["controller"]=> string(5) "index"
["action"]=> string(5)"index"
["module"]=> string(7) "default"
[2]=> array(8) {
["g_goal_list_id"]=> string(3) "127"
["textgoal"]=> string(9) "eats food"
["task_0"]=> string(1) "0"
["value_0"]=> string(5) "pukes"
["task_1"]=> string(1) "0"
["value_1"]=> string(0) ""
["task_2"]=> string(1) "0"
["value_2"]=> string(0) ""
}
[3]=> array(10) {
["g_goal_list_id"]=> string(3) "128"
["textgoal"]=> string(9) "goes home"
["task_0"]=> string(1) "0"
["value_0"]=> string(20) "but never comes back"
["task_1"]=> string(1) "0"
["value_1"]=> string(14) "stays home now"
["task_2"]=> string(1) "0"
["value_2"]=> string(0) ""
["task_3"]=> string(1) "0"
["value_3"]=> string(0) ""
}
["submit"]=> string(4) "Save"
["task"]=> string(1) "5"
}
which is all correct. However, I'm trying to use a foreach statment to grab values from the $request array and put them into a data array, and then submit that to the mysql db...
foreach($request as $currentrow){
//skips row if the field is empty
if(strlen($currentrow['value']) < 1)//need to make sure I've defined $currentrow['value']
continue;//skips row with empty field
//I only need to grab the value/list_id/account_id from the form
$data = array('value' => $currentrow['value'],
'g_goal_list_id' => $currentrow['g_goal_list_id'],
'account_id' => g_getAccountId(),
);
var_dump($data);
However, when I var_dump($data); my output looks like this:
array(3) { ["value"]=> string(1) "i" ["g_goal_list_id"]=> string(1) "i" ["account_id"]=> string(1) "1" }
array(3) { ["value"]=> string(1) "S" ["g_goal_list_id"]=> string(1) "S" ["account_id"]=> string(1) "1" }
array(3) { ["value"]=> string(1) "5" ["g_goal_list_id"]=> string(1) "5" ["account_id"]=> string(1) "1" }
The only thing that is correct in that var_dump($data) is the ["account_id"]
I'm thinking that my loop is incorrect, and I'm pretty bad with loops. Sooooo yeah, hopefully I included enough information. Thank you.

What you need is something like this:
foreach($request as $k=>$currentrow)
{
$hit = false;
$data = array();
// Only look for sub-arrays
if(is_array($currentrow))
{
foreach($currentrow as $k2=>$v2)
{
$explode = explode('_', $k2);
if($explode[0] === 'value') //need to make sure I've defined $currentrow['value'] regardless of suffix
{
$hit = true;
$data = array(
'value' => $v2,
'g_goal_list_id' => $currentrow[$k]['g_goal_list_id'],
'account_id' => g_getAccountId(),
);
continue;
}
}
}
if($hit === false)
{
continue;
}
var_dump($data);
}

This element: $currentrow['values'] does not exist (check your logs, you should see notices). Neither does $currentrow['g_goal_list_id'].
You loop through an array with all different elements, the first being a string, with value index. When you then take that string and subscribe that with values, it throws a warning, but then takes the first element.
To clarify, a some CLI code:
php > $a="abcd";
php > echo $a["foo"];
PHP Warning: Illegal string offset 'foo' in php shell code on line 1
a
If you want to loop over keys and values, do like this:
foreach($request as $key=>$value) {
}
That being said, I think a loop is not what you want, you do not have straighforward table-like data.

Huge thanks to #MonkeyZeus. I kept on getting an array that had the proper keys but all the values were null. Turns out I just needed to put my var_dump($data) inside of my loop, because when it was on the outside it was returning only the last array it looped thorough. On my form the last values it loops through were empty fields, that are meant for the user to add input. Also, I had to change 'g_goal_list_id' => $currentrow[$k]['g_goal_list_id'] to just 'g_goal_list_id' => $currentrow['g_goal_list_id']
foreach ($request as $k=> $currentrow) {
$hit = false;
$data = array();
if(is_array($currentrow)){
foreach ($currentrow as $k2 => $v2) {
$explode = explode('_', $k2); //blows off the suffix of the $key
//var_dump($explode);
//$explode=substr($explode,2);
//echo $k2;
//echo '******';
//echo $v2;
echo $explode[0];
echo '/';
if($explode[0] == 'value'){
//echo "[" . $currentrow['g_goal_list_id'] . "]";
$hit = true;
$data = array(
'value' => $v2,
'g_goal_list_id' => $currentrow['g_goal_list_id'],
'account_id'=> g_getAccountId(),
);
continue;
}
var_dump($data);
}
}
if ($hit === false){
continue;
}
break;
}

Related

Remove empty entries in associated array php

I have tried all the solutions suggested in this post but have not been able to make them work in my case.
My array :
array(2) {
["number_s"]=>
array(14) {
[0]=>
string(2) "22"
[1]=>
string(2) "23"
[2]=>
string(0) ""
[3]=>
string(0) ""
[4]=>
string(0) ""
}
["player_name"]=>
array(14) {
[0]=>
string(9) "John Doe"
[1]=>
string(11) "Jack Sparrow"
[2]=>
string(0) ""
[3]=>
string(0) ""
[4]=>
string(0) ""
}
}
I would like to remove all the empty entries but how to do that ?
Thanks a lot for help
It seems like array_filter for each subarray will do what you want.
$array['number_s'] = array_filter($array['number_s']);
$array['player_name'] = array_filter($array['player_name']);
When called without callback function it just removes all empty entries. See docs for details.
But be aware that it will remove "0" and all values which considered empty.
Assuming there aren't arbitrary numbers of subarrays, you may transverse them (as references) and use unset to remove them from the array:
foreach ($array as &$subarray) {
foreach ($subarray as $key => $value) {
if (empty($value)) {
unset($subarray[$key]);
}
}
}
It's simpler with a functional approach:
$array = array_map(
fn($subarray) => array_filter($subarray),
$array
);
If the array may have arbitrary levels, you may implement a recursive function:
function remove_empty_recursive(array &$array)
{
foreach($array as $key => &$value) {
if (empty($value)) {
unset($array[$key]);
} elseif (is_array($value)) {
remove_empty_recursive($value);
}
}
}
Notice all those solutions assume you want to remove "0", 0 and false from the array. Otherwise, you need to specify another criteria, instead of using empty. For instance:
$array = array_map(
fn($subarray) => array_filter(
$subarray,
fn($value) => !empty($value) || is_numeric($value) || $value === false
),
$array
);

Query gives one indexed array with many elements

I have code like this:
$ch = #new mysqli ($config['db']['host'],$config['db']['user'],$config['db']['password'],$config['db']['database']);
if($result = $ch->query("SELECT pid FROM posts"))
{
while($pids = $result->fetch_assoc())
{
var_dump($pids);
}
var_dump gives me:
array(1) { ["pid"]=> string(1) "1" } array(1) { ["pid"]=> string(1) "2" } array(1) { ["pid"]=> string(1) "3" } array(1) { ["pid"]=> string(1) "4" }
I have two problems:
In database column 'pid' is an int type but the query yields an array of strings
All records from database (4) are saved in one row in an array (got only one index)
Because of that I can't use max(), because it gives me all records (4321).
You have got 4. Check correctly. The var_dump() executes four times, returning a single array (column - row values):
array(1) {
["pid"]=> string(1) "1"
}
array(1) {
["pid"]=> string(1) "2"
}
array(1) {
["pid"]=> string(1) "3"
}
array(1) {
["pid"]=> string(1) "4"
}
If you want everything to be in a single variable, use:
$allPids = array();
while (false != ($pids = $result->fetch_assoc())) {
$allPids[] = $pids;
}
var_dump($allPids);
You need to store them in one array first.
while($pids = $result->fetch_assoc())
{
$array[] = $pids;
}
var_dump($array);
And for the data type PHP will cast them accordingly.

PHP: Combining data with a shared key from a single array into new array

I have this array:
array(5) {
[0]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[1]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
[2]=>
array(4) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTextSeq"]=>
string(1) "3"
["productTxtVal"]=>
string(5) "Text3"
}
[3]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "1"
["productTxtVal"]=>
string(5) "Text1"
}
[4]=>
array(4) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTextSeq"]=>
string(1) "2"
["productTxtVal"]=>
string(5) "Text2"
}
}
With the above input, I want the output array to look like this:
array(2) {
[0]=>
array(3) {
["productCode"]=>
string(4) "X001"
["productUPC"]=>
string(3) "261"
["productTxtVal"]=>
string(17) "Text1 Text2 Text3"
}
[1]=>
array(3) {
["productCode"]=>
string(4) "X002"
["productUPC"]=>
string(3) "262"
["productTxtVal"]=>
string(11) "Text1 Text2"
}
}
The resulting array does not need the productTextSeq key, just the combined values of productTextVal, when the productCode is the same. I've searched SO for examples of this but it seems every example I've found are based on multiple input arrays. I know I can brute force this with nested foreach functions but would love a more elegant solution.
I ended up just doing it the brute force method, here is my solution if anyone's interested:
$productData = array();
$sortedData = array();
$comments = '';
$saveKey = '';
$appendComment = false;
$idx = 0;
foreach ($data as $key=>$value) {
foreach ($value as $k=>$v) {
if ($k == 'productCode') {
if ($v == $saveKey) {
$appendComment = true;
} else {
$appendComment = false;
$saveKey = $v;
if ($idx !== 0) { // Don't write to array on first iteration!
$productData['productTxtVal'] = $comments;
$sortedData[] = $productData;
}
}
}
if ($k == 'productTxtVal') {
if ($appendComment == true) {
$comments .= ' ' . trim($v);
} else {
$comments = trim($v);
}
}
}
$productData = $value;
$idx++;
}
Not "elegant" but it works. I also have a check after this logic in case only one productCode is in the original array, as it won't be written to the $sortedData array since the key never changes.
The following code assumes you control the contents of the original data array (due to risk of injection using extract() function) and that no 2 items with the same productCode have the same productTextSeq.
$products = [];
foreach ($data as $item) {
// extract contents of item array into variables
extract($item);
if (!isset($products[$productCode])) {
// create product array with code, upc, text as array
$products[$productCode] = compact('productCode', 'productUPC') + ['productTxtVal' => []];
}
// add text value to array with sequence as index
$products[$productCode]['productTxtVal'][$productTextSeq] = $productTxtVal;
}
$products = array_values( // ignore array keys
array_map(function($product) {
ksort($product['productTxtVal']); // sort text as array by index/ sequence
$product['productTxtVal'] = implode(' ', $product['productTxtVal']); // implode into string
return $product;
}, $products)
);
You can run the code here: https://repl.it/BWQL

How to create a dynamic array with this set of items

array(3) {
[0]=>
array(4) {
["Field1"]=>
string(8) "80000007"
["Field2"]=>
string(16) "O70000006"
["Field3"]=>
string(0) ""
["Field4"]=>12345
string(0) ""
}
[1]=>
array(4) {
["Field1"]=>
string(8) "80000008"
["Field2"]=>
string(16) "O70000007"
["Field3"]=>
string(0) ""
["Field4"]=>78965
string(0) ""
}
[2]=>
array(4) {
["Field1"]=>
string(8) "80000009"
["Field2"]=>
string(16) "H80000006"
["Field3"]=>
string(0) ""
["Field4"]=>12345
string(0) ""
}
}
I have the above array i want to store this items of array into another temp array and use it . Here is what iam doing
$arr_tmp = array();
foreach ($result['record'] as $key => $value){
$arr_tmp['Field1'] = $value['Field1'];
$arr_tmp['Field2'] = $value['Field2'];
$arr_tmp['Field3'] = $value['Field3'];
$arr_tmp['Field4'] = $value['Field4'];
}
when i do var_dump($arr_tmp). Iam getting only the last record in the array. I need the same result set in this $arr_tmp when using foreach loop so that i can add some more items to this array .
You've only created a single arr_tmp array, and overwrite the values on each loop iteration. Possibly you'd want something like:
$arr_tmp[] = array('Field1' => $value['Field1'], 'Field2' => $value['Field2'], etc...)
inside the loop instead.
But, unless I'm reading your original array wrong, this will simply re-create the original array with new keys, so that begs the question... why? Wouldn't it be easier to just do:
$arr_tmp = $original_array;
?
$arr_tmp = array();
foreach ($result['record'] as $key => $value){
$cur = array();
$cur['Field1'] = $value['Field1'];
$cur['Field2'] = $value['Field2'];
$cur['Field3'] = $value['Field3'];
$cur['Field4'] = $value['Field4'];
$arr_tmp[] = $cur;
}

How to build this kind of Logic using arrays in PHP

I have an array which consists of this set of items
array(3) {
[0]=>
array(4) {
["Field1"]=>
string(8) "80000007"
["Field2"]=>
string(16) "O70000006"
["Field3"]=>
string(0) ""
["Field4"]=>12345
string(0) ""
}
[1]=>
array(4) {
["Field1"]=>
string(8) "80000008"
["Field2"]=>
string(16) "O70000007"
["Field3"]=>
string(0) ""
["Field4"]=>78965
string(0) ""
}
[2]=>
array(4) {
["Field1"]=>
string(8) "80000009"
["Field2"]=>
string(16) "H80000006"
["Field3"]=>
string(0) ""
["Field4"]=>12345
string(0) ""
}
}
Now my question is Iam trying to display only the items once from array or trying to filter the array in such a way if the "Field2" has
a value starting with "O" or "H" and their "Field4 " value should be different . If the "Field4" value is same for the each of the row
then we dont display that row or array item . For eaxample from the above array we will get 2 items as follows
1)80000007 O70000006 12345
2)80000008 O70000007 78965
//we are not displaying the 3rd Item
because The "Field4 " is same . we
display only once
foreach ($resultset as $key => $value){
echo $key."<br>"; /// outputs 0,1,2
echo $value['Field2']."<br>"; // outputs O70000006, O70000007, H80000006
}
function getField2_removeDupeField4($arr){
$f4 = array();
$f2 = array();
foreach($arr as $array){
if(in_array($array['Feild4'], $f4){ continue; }
$firstChar = substr($array['Feild2'], 0, 1);
if($firstChar == 'O' || $firstChar == 'H'){
$f2[] = $array;
$f4[] = $array['Feild4'];
}
}
return $f2;
}
So to get the array you want:
$new_arr = getField2_removeDupeField4($orig_arr);
So... you just want some way to skip rows whose Field4 has already been printed?
Set up an array to hold all the previously printed Field4s, and check against that before printing anything. Something like this:
$field4s = array();
foreach ($resultset as $key => $value){
$field4 = $value['Field4'];
if (($field4[0] == 'O' || $field4[0]=='H') && !in_array($field4 , $field4s) {
array_push($field4s, $field4);
echo $field4;
}
}

Categories