Creating a nested array form a flat array trough Parent ID - php

I want to make my flat array to a nested array but I can't seem to do this ;/
the code that I tryed to make it nested with:
<?php
$link = mysqli_connect("localhost", "db_phpnav", "jeXS9ftZhmJdzRWd", "db_phpNav");
$sql = "SELECT ID, PID, Naam FROM tb_nav";
$result = mysqli_query($link, $sql);
function convertToTree(array $flat, $idField = 'ID',
$parentIdField = 'PID',
$childNodesField = 'childNodes') {
$indexed = array();
foreach ($flat as $row) {
$indexed[$row[$idField]] = $row;
$indexed[$row[$idField]][$childNodesField] = array();
}
$root = null;
foreach ($indexed as $id => $row) {
$indexed[$row[$parentIdField]][$childNodesField][$id] =& $indexed[$id];
if (!$row[$parentIdField]) {
$root = $id;
}
}
return array($root => $indexed[$root]);
}
$rows = array();
while($row = mysqli_fetch_assoc($result)) {
$rows[] = $row;
}
convertToTree($rows);
?>
the array it gives out. it clearly doesn't do what I intended for.
array(3) {
[0]=>
array(3) {
["ID"]=>
string(1) "2"
["PID"]=>
NULL
["Naam"]=>
string(7) "Contact"
}
[1]=>
array(3) {
["ID"]=>
string(1) "5"
["PID"]=>
string(1) "2"
["Naam"]=>
string(7) "testing"
}
[2]=>
array(3) {
["ID"]=>
string(1) "6"
["PID"]=>
NULL
["Naam"]=>
string(8) "testing2"
}
}
How do i get the array to be nested nicely?
it should look more like this:
[0]=>
array(3) {
["ID"]=>
string(1) "2"
["PID"]=>
NULL
["Naam"]=>
string(7) "Contact"
'childNodes' => array(
2 => array(
["ID"]=>
string(1) "5"
["PID"]=>
string(1) "2"
["Naam"]=>
string(7) "testing"
'childNodes' => array ();
);
}

Suppose this is (kind of) what you want:
<?PHP
$entries = array();
$entries[] = array("ID" => "2", "PID" => NULL, "Naam" => "Contact");
$entries[] = array("ID" => "5", "PID" => "2", "Naam" => "testing");
$entries[] = array("ID" => "6", "PID" => NULL, "Naam" => "testing2");
function convertToTree($flat, $idField = 'ID', $parentIdField = 'PID', $childNodesField = 'childNodes', $curIdx = NULL)
{
$indexed = array();
foreach($flat as $row)
{
if ($row[$parentIdField] == $curIdx)
{
$indexed[$row[$idField]] = $row;
$indexed[$row[$idField]]["childNodes"] = convertToTree($flat, $idField, $parentIdField, $childNodesField, $row[$idField]);
}
}
return $indexed;
}
print_r($entries);
$tree = convertToTree($entries);
print_r($tree);
?>

/**
* Transform array to a nested structure.
* This gets a little complicated. Basically, we're creating a placeholder in
* $children to hold the child terms of each parent term. Then we create a
* reference to that element in the parent term. So nesting happens via magic.
*/
function arrayFlatToNested($array, $idKey = 'ID', $parentIdKey = 'PID', $childrenKey = 'childNodes'): array
{
$arrayNested = [];
$children = [];
foreach ($array as $element) {
// Create a placeholder for the object's children.
if (!isset($children[$element[$idKey]])) {
$children[$element[$idKey]] = [];
}
// Create a link to those children.
$element[$childrenKey] = &$children[$element[$idKey]];
if (!strlen($element[$parentIdKey])) {
$arrayNested[] = $element;
} else {
// Create a placeholder for the parent.
if (!isset($children[$element[$parentIdKey]])) {
$children[$element[$parentIdKey]] = [];
}
// Add this object to the parent, even if it doesn't exist yet.
$children[$element[$parentIdKey]][] = $element;
}
}
return $arrayNested;
}

Related

What is the best way to group a php array?

For example, I have this array:
$bills = array(
array("bill_id"=>"1", "product_id"=>"1", "total"=>"10"),
array("bill_id"=>"2", "product_id"=>"2", "total"=>"20"),
array("bill_id"=>"3", "product_id"=>"1", "total"=>"30"),
array("bill_id"=>"4", "product_id"=>"1", "total"=>"40"),
array("bill_id"=>"5", "product_id"=>"2", "total"=>"50")
);
We need to add the totals of each produdct into a single array, i.e. What is the best clean fast way to generate the following array from the above one:
$products = array(
array("product_id"=>"1", "total"=>"80"),
array("product_id"=>"2", "total"=>"70")
);
the fastest way to sum this is index array, something like this
$products = array();
foreach ($bills as $bill) {
$key = $bill['product_id'];
if (isset($products[$key])) {
$products[$key]['total'] += $bill['total'];
} else {
$products[$key] = $bill;
}
}
var_dump($products);
output
array(2) {
[1]=>
array(3) {
["bill_id"]=>
string(1) "1"
["product_id"]=>
string(1) "1"
["total"]=>
int(80)
}
[2]=>
array(3) {
["bill_id"]=>
string(1) "2"
["product_id"]=>
string(1) "2"
["total"]=>
int(70)
}
}
to browse the invoice list
foreach($products as $key=>$bill) {
var_dump($bill);
}
Thie simplest approach is a single-pass loop.
$byProduct = [];
foreach($bills as $bill)
{
$key = $bill['product_id'];
if (!isset($byProduct[$key])) {
$byProduct[$key] = [
'product_id' => $key,
'total' => 0
];
}
$byProduct[$key]['total'] += $bill['total'];
}
Result of var_dump($byProduct):
array(2) {
[1] =>
array(2) {
'product_id' =>
string(1) "1"
'total' =>
int(80)
}
[2] =>
array(2) {
'product_id' =>
string(1) "2"
'total' =>
int(70)
}
}
Another approach is to use array_walk but it is pretty much the same in terms of complexity:
$byProduct = [];
array_walk($bills, function(&$bill) use (&$byProduct) {
$key = $bill['product_id'];
if (!isset($byProduct[$key])) {
$byProduct[$key] = [
'product_id' => $key,
'total' => 0
];
}
$byProduct[$key]['total'] += $bill['total'];
});

Combine multiple form array into 1 array

["trnx_date"]=>
array(2) {
[0]=>
string(10) "2017-01-10"
[1]=>
string(10) "2017-01-10"
}
["curr_from"]=>
array(2) {
[0]=>
string(3) "USD"
[1]=>
string(3) "PHP"
}
["curr_from_amt"]=>
array(2) {
[0]=>
string(8) "4,000.00"
[1]=>
string(8) "3,000.00"
}
["curr_to"]=>
array(2) {
[0]=>
string(3) "GBP"
[1]=>
string(3) "SAR"
}
["curr_to_amt"]=>
array(2) {
[0]=>
string(8) "3,000.00"
[1]=>
string(8) "2,000.00"
}
["amount"]=>
array(2) {
[0]=>
string(8) "7,000.00"
[1]=>
string(8) "5,000.00"
}
I have the above array which was being submitted. This input was in sets of multiple field which was generated by dynamic table row. How can I group this into 1 (one) array so that I could save in the database? Like this:
[cust_row] => array(
'tranx_date' => "2017-01-10",
'curr_from' => "USD",
'curr_from_amt' => "4,000.00",
'curr_to' => "GBP",
'curr_to_amt' => "3,000.00",
'amount' => "7,000.00"
),
[cust_row] => array(
'tranx_date' => "2017-01-10",
'curr_from' => "PHP",
'curr_from_amt' => "3,000.00",
'curr_to' => "SAR",
'curr_to_amt' => "2,000.00",
'amount' => "5,000.00"
),
All of the above we being populated like this:
$trnx_date = $this->input->post('trnx_date');
$curr_from = $this->input->post('curr_from');
$curr_from_amt = $this->input->post('curr_from_amt');
$curr_to = $this->input->post('curr_to');
$curr_to_amt = $this->input->post('curr_to_amt');
$amount = $this->input->post('amount');
Assuming all the sub-arrays have the same length, you can use a simple for loop that iterates over the index of one of them, and use that to access each of the sub-arrays at that index. Then combine all of them into the associative array for each customer.
$result = array();
$keys = array_keys($array);
$len = count($array[$keys[0]]); // Get the length of one of the sub-arrays
for ($i = 0; $i < $len; $i++) {
$new = array();
foreach ($keys as $k) {
$new[$k] = $array[$k][$i];
}
$result[] = $new;
}
$arr = array(
'trnx_date' => array('2017-01-10', '2017-01-10'),
'curr_from' => array('USD', 'PHP'),
'curr_from_amt' => array('4,000.00', '3,000.00'),
'curr_to' => array('GBP', 'SAR'),
'curr_to_amt' => array('3,000.00', '2,000.00'),
'amount' => array('7,000.00', '5,000.00')
);
$arr_out = array();
$arr_keys = array_keys($arr);
for($i = 0; $i < count($arr[$arr_keys[0]]); $i++) {
$new_arr = array();
foreach($arr_keys as $key => $value) {
$new_arr[$value] = $arr[$value][$i];
}
$arr_out[] = $new_arr;
}
var_dump($arr_out);
Hope it helps!
How about this?
// assume $arr is your original data array
$keys = array_keys($arr);
$result = array();
foreach($keys as $key) {
$vals = $arr[$key];
foreach($vals as $i =>$val) {
if (!is_array($result[$i]) {
$result[$i] = array();
}
$result[$i][$key] = $val;
}
}
var_dump($result);
EDIT: added array check for $result[$i]

How to get table data with foreach if my array indexs' are the same

$query = mysqli_query($con,"SELECT id,title,post FROM titlepost");
$data = [];
while($row = mysqli_fetch_assoc($query))
{
$data = $row;
var_dump($data);
}
With this code I get
array(3) { ["id"] => string(1) "1" ["title"] => string(4) "News" ["post"] => string(21) "Here can be your news"
}
array(3) { ["id"] => string(1) "4" ["title"] => string(5) "Maths" ["post"] => string(30) "Here can be your maths' theory"
}
array(3) { ["id"] => string(1) "5" ["title"] => string(6) "Toyota" ["post"] => string(26) "Here can be your car's add"
}
Here I want to get the data with foreach
<?php
foreach($data as $value) { ?>
<tr>
<th><?=$value['id']?></th>
<th><?=$value['title']?></th>
<th><?=$value['post']?></th>
</tr>
<?php }?>
There is no need to use two separate loops. You can just output the values within the first loop:
$query = mysqli_query($con,"SELECT id,title,post FROM titlepost");
while($row = mysqli_fetch_assoc($query)) {
?><tr>
<th><?=$row['id']?></th>
<th><?=$row['title']?></th>
<th><?=$row['post']?></th>
</tr><?php
}
However, if you want for some reason to store the result in an array (for example to use it multiple times or pass it to a view in an MVC setup), your first loop should look like this:
$query = mysqli_query($con,"SELECT id,title,post FROM titlepost");
$data = [];
while($row = mysqli_fetch_assoc($query))
{
$data[] = $row; // this line appends a new item to the $data array, instead of overwriting it, like in your original code
}

Insert data to array php pdo

I have this code:
$rows = array();
$table = array();
foreach($kol as $r) {
$temp = array();
// the following line will be used to slice the Pie chart
$m = array('label' => (string) $r['naziv'], 'type' => 'string');
$rows[] = ($m);
}
$table['cols'] = $rows;
and I get this json:
{"cols":[{"label":"Pera Peric","type":"string"},{"label":"IMT 510-td","type":"string"},{"label":"Laza Lazic","type":"string"}
How I can put data on $m array to position 0 to get json like this:
{"cols":[{"label":"Datum,"type":"Date"},{"label":"Pera Peric","type":"string"},{"label":"IMT 510-td","type":"string"},{"label":"Laza Lazic","type":"string"}
so here I just want to add this data: {"label":"Datum,"type":"Date"} to array ...
Just add it before you start your loop (I cleaned a bit):
$rows = array();
$table = array();
$rows[] = array('label' => 'Datum', 'type' => 'Date')
foreach ($kol as $r) {
$rows[] = array('label' => (string) $r['naziv'], 'type' => 'string');
}
$table['cols'] = $rows;
array_unshift()
<?php
// your json
$json = '{"cols":[{"label":"Pera Peric","type":"string"},{"label":"IMT 510-td","type":"string"},{"label":"Laza Lazic","type":"string"}]}';
// json array to php array using json_decode()
$json_decode = json_decode($json, true);
// your $m php array
$m = array(
'label' => 'Datum',
'type' => 'Date'
);
// add you $m to position 0 in index 'cols'
array_unshift($json_decode['cols'], $m);
Done!
array(1) {
["cols"]=>
array(4) {
[0]=>
array(2) {
["label"]=>
string(5) "Datum"
["type"]=>
string(4) "Date"
}
[1]=>
array(2) {
["label"]=>
string(10) "Pera Peric"
["type"]=>
string(6) "string"
}
[2]=>
array(2) {
["label"]=>
string(10) "IMT 510-td"
["type"]=>
string(6) "string"
}
[3]=>
array(2) {
["label"]=>
string(10) "Laza Lazic"
["type"]=>
string(6) "string"
}
}
}
Back to json (if you want)
$json = json_encode($json_decode);

Zend Framework Using fetch() statement in a loop, internal query doesn't work

I can't solve this one.
I have multiple while, and the one inside fetch only the first result and stop ...
Here is the code :
$categories is an array
array(18) {
[0] => array(7) {
["category_id"] => string(1) "1"
["category_name"] => string(5) "pizza"
["category_display"] => string(5) "pizza"
["category_active"] => string(1) "1"
["category_parent"] => string(1) "0"
["category_position"] => string(1) "1"
["category_user_discount"] => string(2) "50"
}
[1] => array(7) {
["category_id"] => string(1) "2"
["category_name"] => string(4) "menu"
["category_display"] => string(4) "menu"
["category_active"] => string(1) "1"
["category_parent"] => string(1) "0"
["category_position"] => string(1) "2"
["category_user_discount"] => string(2) "30"
}
}
$stmt = $db->query("SELECT sell_id FROM sell WHERE sell.sell_status = 'close' AND sell_period_id >= '".$liste[0]."' AND sell_period_id <= '".$liste[1]."' ");
foreach ($categories as $cat)
{
while ($sell2 = $stmt->fetch())
{
$stmt2 = $this->db->query("SELECT * FROM sellcart WHERE sellcart_status = 'close' AND sellcart_sell_id = '".$sell2['sell_id']."' ");
while ($sellitem = $stmt2->fetch())
{
echo $sellitem['sellcart_item_category'];
}
}
}
The first loop is OK, but it doesn't loop into the second $cat ...
Any idea ?
Thanks for your help !!!
I know is too late for an answer but, the problem is, after the second fetch php close the connection or has no more values for the first fetch and return false. Maybe can you try out with a second connection for the second fetch.
Sorry for my English.
// for example ..............
$db = Zend_Db::factory($config["database"]["adapter"],$config["database"] ["params"]);
$db2 = $db = Zend_Db::factory($config["database"]["adapter"],$config["database"]["params"]);
// .......
$stmt = $db->query("SELECT sell_id FROM sell WHERE sell.sell_status = 'close' AND sell_period_id >= '".$liste[0]."' AND sell_period_id <= '".$liste[1]."' ");
foreach ($categories as $cat) {
while ($sell2 = $stmt->fetch()) {
$stmt2 = $db2->query("SELECT * FROM sellcart WHERE sellcart_status = 'close' AND sellcart_sell_id = '".$sell2['sell_id']."' ");
while ($sellitem = $stmt2->fetch()) {
echo $sellitem['sellcart_item_category'];
}
}
}

Categories