Multi Dimensional Array Construct - php

I have this type of array that I got from my SQL result.
+-------------+---------------+-----------------+----------------+
| business_id | business_name | business_branch | branch_contact |
+-------------+---------------+-----------------+----------------+
| 1 | ABC | 1 | 1111111111 |
+-------------+---------------+-----------------+----------------+
| 1 | ABC | 2 | 2222222222 |
+-------------+---------------+-----------------+----------------+
| 1 | ABC | 3 | 3333333333 |
+-------------+---------------+-----------------+----------------+
| 1 | ABC | 4 | 4444444444 |
+-------------+---------------+-----------------+----------------+
| 2 | XYZ | 1 | 5555555555 |
+-------------+---------------+-----------------+----------------+
| 2 | XYZ | 2 | 6666666666 |
+-------------+---------------+-----------------+----------------+
At the beginning I thought of doing a separate database query for each branches and businesses. But got to know it was a bad practice.
I want to construct the results as following
[
{
business_id : 1,
business_name : ABC,
branches : [
{
branch_id : 1,
branch_contact : 1111111111
},
{
branch_id : 2,
branch_contact : 2222222222
},
...
},
{
business_id : 1,
business_name : ABC,
branches : [
{
...
}
}
]
}
The current function I'm trying to build doesn't give the necessary output. It is shown below.
$previousBusiness = '';
$previousBranch = '';
$businessAndBranchArray = [];
$businessArray = [];
$branchArray = [];
foreach ($results as $result) {
$currentBranch = [];
$currentBusiness = [];
$currentMerchant = [];
if($result['business_id'] != $previousBusiness && $result['branch_id'] != $previousBranch){
if($previousBranch != '' && $previousBusiness != ''){
$businessArray['business_id'] = $result['business_id'];
$businessArray['business_id'] = $result['business_name'];
$branchArray['branch_id'] = $result['branch_id'];
$branchArray['branch_contact'] = $result['branch_contact'];
} else {
$businessArray['business_id'] = $result['business_id'];
$businessArray['business_id'] = $result['business_name'];
$branchArray['branch_id'] = $result['branch_id'];
$branchArray['branch_contact'] = $result['branch_contact'];
}
$previousBusiness = $result['business_id'];
} else {
$branchArray['branch_id'] = $result['branch_id'];
$branchArray['branch_contact'] = $result['branch_contact'];
}
}

No need to keep track of previous items and such, just use the ID as an array key so you can check it exists. If you don't want it in your final output, use array_values() to remove the keys:
<?php
$results = [
["business_id" => 1, "business_name" => "ABC", "business_branch" => 1, "branch_contact" => "1111111111"],
["business_id" => 1, "business_name" => "ABC", "business_branch" => 2, "branch_contact" => "2222222222"],
["business_id" => 1, "business_name" => "ABC", "business_branch" => 3, "branch_contact" => "3333333333"],
["business_id" => 1, "business_name" => "ABC", "business_branch" => 4, "branch_contact" => "4444444444"],
["business_id" => 2, "business_name" => "XYZ", "business_branch" => 1, "branch_contact" => "5555555555"],
["business_id" => 2, "business_name" => "XYZ", "business_branch" => 2, "branch_contact" => "6666666666"],
];
$output = [];
foreach ($results as $result) {
if (empty($output[$result["business_id"]])) {
$output[$result["business_id"]] = [
"business_id" => $result["business_id"],
"business_name" => $result["business_name"],
"branches" => [],
];
}
$output[$result["business_id"]]["branches"][] = [
"branch_id" => $result["business_branch"],
"branch_contact" => $result["branch_contact"],
];
}
echo json_encode(array_values($output), true);
Output:
[{"business_id":1,"business_name":"ABC","branches":[{"branch_id":1,"branch_contact":"1111111111"},{"branch_id":2,"branch_contact":"2222222222"},{"branch_id":3,"branch_contact":"3333333333"},{"branch_id":4,"branch_contact":"4444444444"}]},{"business_id":2,"business_name":"XYZ","branches":[{"branch_id":1,"branch_contact":"5555555555"},{"branch_id":2,"branch_contact":"6666666666"}]}]

Related

Creating nested json for hotel system

I want to create a nested json that comes with post.
I have 3 fields. Adults, children and baby. But, there are also dates for children and baby areas. For example; Children 1 Birthday, Children 2 Birthday, Baby 1 Birthday, Baby 2 Birthday
When I try with the code below, I can't print child dates by room. Writes in bulk. How can I POST with php like json below?
+---------+----------+-------+
| Adults | Children | Baby | (select box field)
+--------------------+--------
| 1 | 0 | 0 |
+--------------------+--------
| 2 | 1 | 1 | (also available for children and baby areas)
+--------------------+-------+
| 3 | 2 | 2 |
+---------+----------+-------+
rooms: [
{
adults: 2,
child: [
child_total: 1
child_date: [
"2017-08-10"
],
],
baby: [
baby_total: 1
baby_date: [
"2017-07-01"
],
],
},
{
adults: 1,
child: [
child_total: 2
child_date: [
"2017-08-08",
"2017-08-09"
],
],
baby: [
baby_total: 2
baby_date: [
"2017-06-08",
"2017-05-09"
],
],
}
],
foreach ($this->input->post('adults') as $key => $value) {
foreach ($_POST['child_total'] as $value2) {
$child_date = [];
foreach ($_POST['child_date'] as $key2 => $value3) {
$child_date[] = $value3;
}
}
$rooms[] = array(
'adults' => $_POST['adults'][$key],
'child' => array(
'child_total' => $_POST['child_total'][$key],
'child_date' => $child_date
)
);
}
print json_encode($rooms, JSON_PRETTY_PRINT);

Laravel Eloquent Nested Group by its Relation

Please help me how to add another nested group by based on game category relation. I have 3 tables related using laravel 5.4 eloquent.
Game Providers Table
+----+-------------+--------------+------------------+
| id | game_name | game_type_id | game_category_id |
+----+-------------+--------------+------------------+
| 1 | Sample | 1 | 1 |
| 1 | Sample 0 | 1 | 2 |
| 2 | Sample 1 | 2 | 1 |
| 3 | Sample 2 | 2 | 2 |
+----+-------------+--------------+------------------+
Game Types
+----+-------------+
| id | name |
+----+-------------+
| 1 | Chess |
| 2 | Poker |
+----+-------------+
Game Categories
+----+-------------+
| id | name |
+----+-------------+
| 1 | Recommended |
| 2 | Optional |
+----+-------------+
I'm done of for first nested for game type relation but i dont know how to add another group by for game categories
$game_providers = GameProvider::all();
$game_providers = $game_providers->groupBy(function ($game_provider) {
return $game_provider->game_type->name;
})->all();
and its output
Array{
'Chess' => Array{
0 => Array{
'id' => 1,
'game_name' => 'Sample',
'game_type_id' => 1,
'game_category_id' => 2
},
1 => Array{
'id' => 2,
'game_name' => 'Sample 0',
'game_type_id' => 1,
'game_category_id' => 2
},
},
'Poker' => Array{
0 => Array{
'id' => 3,
'game_name' => 'Sample 1',
'game_type_id' => 2,
'game_category_id' => 1
},
1 => Array{
'id' => 4,
'game_name' => 'Sample 2',
'game_type_id' => 2,
'game_category_id' => 2
},
},
}
My expected output
Array{
'Chess' => Array{
'Recommended' => Array{
0 => Array{
'id' => 1,
'game_name' => 'Sample',
'game_type_id' => 1,
'game_category_id' => 2
}
},
'Optional' => Array{
0 => Array{
'id' => 2,
'game_name' => 'Sample 0',
'game_type_id' => 1,
'game_category_id' => 2
}
}
},
'Poker' => Array{
'Recommended' => Array{
0 => Array{
'id' => 3,
'game_name' => 'Sample 1',
'game_type_id' => 2,
'game_category_id' => 1
}
},
'Optional' => Array{
0 => Array{
'id' => 4,
'game_name' => 'Sample 2',
'game_type_id' => 2,
'game_category_id' => 2
}
}
}
}
With L5, one way of acieving this can be:
GameProvider::with('game_categories.game_types')
->get()
->groupBy([
'gameTypes.name',
'gameCategories.name'
]);
Should be something along the lines of :
GameProvider::with('game_categories.game_types')->get()->map(function ($game) {
return $game->game_categories->groupBy('name')->map(function ($catGame) {
return $catGame->map(function ($category) {
return $category->game_types->groupBy('name');
});
});
});

How to edit key/value pairs in multidimensional, associative arrays?

I hope my title makes sense, I'm no quite sure how to describe my problem in a shot way, so here is the long version:
I'm working in PHP and I have 2 MySQL tables that are displaying items and their specs (I cannot change the table structure).
T1 (Items)
+---------+--------+
| itemID | item |
+---------+--------+
| 1 | TV |
| 2 | Radio |
| 3 | Camera |
| ... | ... |
+---------+--------+
T2 (Specs)
+---------+--------+------+
| itemID | specID | spec |
+---------+--------+------+
| 1 | color | red |
| 1 | weight | 10 |
| 1 | price | 499 |
| 2 | color | blue |
| ... | ... | ... |
+---------+--------+------+
I want a multidimensional, associative array like this
array(
[0]=> array(
"itemID"=>"1",
"item"=>"TV",
"color"=>"red",
"weight"=>"10",
"price"=>"499")
[1]=> array(
"itemID"=>"2",
"item"=>"Radio",
"color"=>"blue",
...)
)
It seems impossible to me to achieve that with only one query.
I try to query the two tables separately, rearrange the key=>value in T2 and use array_merge.
What I have so far is the array from T1
array(
[0]=> array(
"itemID"=> "1",
"item"=>"TV")
[1]=> array(
"itemID"=> "2",
"item"=>"Radio")
[2]=> array(
"itemID"=> "3",
"item"=>"Camera")
...)
From T2 the array comes in the same form
array(
[0]=> array(
"itemID"=> "1",
"specID"=> "color",
"spec"=>"red")
[1]=> array(
"itemID"=> "1",
"specID"=> "weight",
"spec"=>"10")
[2]=> array(
"itemID"=> "1",
"specID"=> "price",
"spec"=>"499")
...)
After changing the array I will get a single numeric array, not two associative arrays like I want
array(
[0]=> array(
[0] => ["itemID" => "1","color" => "red","weight" => "10", "price" => "499"])
[1]=> array(
[0] => ["itemID" => "2","color" => "blue",...])
...)
My code is
$newArray = array();
for ($i = 0; $i<=n; $i++) {
foreach($oldArray[$i] as $key => $value) {
if ($key === 'itemID') {
$a = $key . '" => "' . $value . '",';
}
elseif($key === 'specID') {
$b = '"' . $key . '" => "';
}
elseif($key === 'spec') {
$c = $value;
}
}
$newArray[] = [$a.$b.$c];
}
Maybe I'm completely wrong here, so any help would be greatly appreciated - Thanks!
This table structure is great if the number of item parameters is variable.
The simplest approach is the following:
$array1 = array(...); // from table 1
$array2 = array(...); // from table 2
$result = array();
foreach ($array1 AS $v) {
$result[ $v['itemID'] ] = $v;
}
foreach ($array2 AS $v) {
$result[ $v['itemID'] ][ $v['specId'] ] = $v['spec'];
}
Consider using group_concat
This will fetch everything you need in 1 query:
select items.itemID,
group_concat(concat(specs.specID,":",specs.spec)) as properties
from items join specs on items.itemID=specs.itemID
group by items.itemID;
Results will look like this:
+--------+-------------------------------+
| itemID | properties |
+--------+-------------------------------+
| 1 | color:red,weight:10,price:499 |
| 2 | color:blue |
+--------+-------------------------------+
I'll leave it to you to populate the array but it should be trivial using explode first with "," delimiter then with ":"

Built a multidimensional array with PHP from an SQL query

Form a SQL query i receive the following datas from two differences tables.
|----------------|----------|--------------|
|CON_ContinentId | FRU_Name | FRU_Quantity |
|----------------|----------|--------------|
| 1 | Apple | 100 |
| 1 | Banana | 200 |
| 2 | Peach | 300 |
| 2 | Cherry | 400 |
| 3 | Coconut | 500 |
| 4 | Grape | 1100 |
| 5 | Pear | 1500 |
|----------------|----------|--------------|
I need to get an array like this:
$datas = [
1 => [
[
'FRU_Name' => 'Apple',
'FRU_Quantity' => '100'
],
[
'FRU_Name' => 'Banana',
'FRU_Quantity' => '200'
]
],
2 => [
[
'FRU_Name' => 'Peach',
'FRU_Quantity' => '300'
],
[
'FRU_Name' => 'Cherry',
'FRU_Quantity' => '400'
]
],
3 => [
[
'FRU_Name' => 'Coconut',
'FRU_Quantity' => '500'
]
],
4 => [
[
'FRU_Name' => 'Grape',
'FRU_Quantity' => '1000'
]
],
5 => [
[
'FRU_Name' => 'Pear',
'FRU_Quantity' => '1100'
]
],
]
So, basically, I need to groupe the rows with the same CON_ContinentId and list the FRU_Name and FRU_Quantity.
What I try:
$datas = [];
while ($fetch = $query->fetch(PDO::FETCH_ASSOC)){
$CON_ContinentId = $fetch['CON_ContinentId'];
$FRU_Name = $fetch['FRU_Name'];
$FRU_Quantity = $fetch['FRU_Quantity'];
if (!in_array($CON_ContinentId, $datas)) {
$datas = array(
'CON_ContinentId' => $CON_ContinentId,
'FRU_Name' => $FRU_Name,
'FRU_Quantity' => $FRU_Quantity
);
}
}
But it doesn't work.
Could you please help me ?
Thanks.
There are a few different problems in your code:
Your desired array structure isn't valid, so it's unclear what you want.
$datas isn't initialized. Use $datas = [] instead.
$FRU_Name is being set twice? Did you mean $FRU_Quantity?
This code won't group multiple fruits under their continent ID--it'll put them into an associative array alongside their continent ID.
Every iteration of your results set, just use the CON_ContinentID value as the key, then [] to auto-index the subarrays.
There is no need to declare resultset values to new variables, just apply them to the $datas declaration and move on.
while ($fetch = $query->fetch(PDO::FETCH_ASSOC)){
$datas[$fetch['CON_ContinentId']][]=['FRU_Name'=>$fetch['FRU_Name'],'FRU_Quantity' =>$fetch['FRU_Quantity']];
}
a bit more explanation...
// hard-coded keys -vvvvvvvv-----------------------vvvvvvvvvvvv
$datas[$fetch['CON_ContinentId']][]=['FRU_Name'=>$fetch['FRU_Name'],'FRU_Quantity' =>$fetch['FRU_Quantity']];
// id-^^^^^^^^^^^^^^^^^^^^^^^^^ ^^-auto-index ^^^^^^^^^^^^^^^^^^------------------^^^^^^^^^^^^^^^^^^^^^^-resultset data
// ^^^^^^^^^^-keys start from zero, and increment by one at each new pushed subarray)

Converting a flat array to a specific array format

Fellow PHP programmers, consider the following DB result:
+---------+-----------+---------------+--------+
| node_id | parent_id | path | branch |
+---------+-----------+---------------+--------+
| 1 | 0 | /1/ | NULL |
| 2 | 1 | /1/2/ | NULL |
| 3 | 2 | /1/2/3/ | 1 |
| 4 | 3 | /1/2/3/4/ | 1 |
| 8 | 4 | /1/2/3/4/8/ | 1 |
| 9 | 8 | /1/2/3/4/8/9/ | 1 |
| 7 | 4 | /1/2/3/4/7/ | 0 |
| 5 | 2 | /1/2/5/ | 0 |
| 6 | 5 | /1/2/5/6/ | 0 |
+---------+-----------+---------------+--------+
How does one get the following PHP array:
[
[
'id' => 1,
'parentId' => 0,
],
[
'id' => 2,
'parentId' => 1,
'nodes' => [
[ // when branch == 0
[
'id' => 5,
'parentId' => 2
],
[
'id' => 6,
'parentId' => 5
],
],
[ // when branch == 1
[
'id' => 3,
'parentId' => 2
],
[
'id' => 4,
'parentId' => 3,
'nodes' => [
[ // when branch == 0
[
'id' => 7,
'parentId' => 4
],
],
[ // when branch == 1
[
'id' => 8,
'parentId' => 4
],
[
'id' => 9,
'parentId' => 8
],
]
]
],
]
]
]
]
The function should work with unlimited depth.
Any help would be greatly appreciated as I've been hitting a wall.
Something like this:
function buildTree($arr, $parentID)
{
$children = [];
foreach ($arr as $item) {
if ($item['parent_id'] == $parentID) {
array_push($children, [
'id' => $item['node_id'],
'parentId' => $item['parent_id'],
'nodes' => buildTree($arr, $item['node_id'])
]);
}
}
return $children;
}
$tree = buildTree($flat, null);
UPD:
function getBranches($arr, $parentID)
{
$branches = array();
foreach ($arr as $item) {
if ($item['parent_id'] == $parentID) {
$bKey = $item['branch'];
$node = array(
'id' => $item['node_id'],
'parentId' => $item['parent_id']
);
$firstNodeChild = false;
if ($nodeChildren = getBranches($arr, $item['node_id'])) {
$hasKey = array_key_exists($bKey, $nodeChildren);
if ($hasKey && $nodeChildren[$bKey]) {
if (sizeof($nodeChildren[$bKey]) == 1) {
$firstNodeChild = $nodeChildren[$bKey][0];
unset($nodeChildren[$bKey]);
}
}
if ($nodeChildren) {
$node['nodes'] = $nodeChildren;
}
}
if (!array_key_exists($bKey, $branches)) {
$branches[$bKey] = array();
}
$branches[$bKey][] = $node;
if (false !== $firstNodeChild) {
$branches[$bKey][] = $firstNodeChild;
}
}
}
ksort($branches);
return $branches;
}
$tree = getBranches($arr, 0);

Categories