Create multidimensional array from rows of data - php

I have a database with project entries. Each entry has a project title, datestamp, the user who entered it, and a comment. I am trying to format this data as JSON for reporting and charts.
I want an array for each project name, and inside that array an array for each entry.
I've tried several approaches but I haven't had much luck yet.
if ($result = $mysqli->query("SELECT * FROM project_entries"))
// WHERE WEEK(date) = WEEK(current_date) ORDER BY project_name
{
while ($row = mysqli_fetch_array($result)) {
$entry_array = array();
$row_array['project_name'] = $row['project_name'];
$comment = $row['comment'];
$entry = array (
'comment' => $comment,
);
$row_array['entries'] = $entry;
if ( !in_array($row['project_name'], $projects, false ))
{
array_push($projects, $row_array);
}
}
}
Outputs:
[
{
"project_name": "Logo Design",
"entries": {
"comment": "Worked on a thing"
}
},
{
"project_name": "Logo Design",
"entries": {
"comment": "Created some stuff"
}
},
While I want:
{
"project_name": "Logo Design",
"entries": {
"comment": "Worked on a thing",
"comment": "Created some stuff"
}
}

This should do the trick. You can use the project name as an array key. In order to prevent the string keys from showing up in your output array, you can use array_values to convert them to numeric keys.
$projects = array();
while ($row = mysqli_fetch_array($result)) {
$projects[$row['project_name']]['project_name'] = $row['project_name'];
$projects[$row['project_name']]['entries'][] = array('comment' => $row['comment']);
}
echo json_encode(array_values($projects));
What was going wrong with your previous code:
if ($result = $mysqli->query("SELECT * FROM project_entries")) {
while ($row = mysqli_fetch_array($result)) {
$entry_array = array(); // This does not appear to be used
// With each iteration of the while loop, you create a new array of
// project information (project name and entries array with one comment)
$row_array['project_name'] = $row['project_name'];
$comment = $row['comment'];
$entry = array ('comment' => $comment);
$row_array['entries'] = $entry;
// The $projects array is an array of arrays, but $row['project_name'] is
// a string. Checking if this string is in an array of arrays will always
// be false, so the array_push should always execute.
if (!in_array($row['project_name'], $projects, false )) {
// Adds the new project array to the projects array
array_push($projects, $row_array);
}
// This is not producing what you want because you are adding a new
// array to $row_array each time the loop runs
}
}
Why the code I suggested works:
$projects = array(); // Empty array to hold all the projects
while ($row = mysqli_fetch_array($result)) {
// Using the project name from the database as an array key in the array we are
// constructing keeps the projects unique in that array.
// The first time a new project name occurs, this will create a new sub-array
// within $projects with project_name => the new project name. This value will
// be overwritten on subsequent occurrences of the same project name.
$projects[$row['project_name']]['project_name'] = $row['project_name'];
// For each iteration, this will add a comment to the 'entries' array in the
// project array with the key $row['project_name'].
$projects[$row['project_name']]['entries'][] = array('comment' => $row['comment']);
// For example, with the first iteration of the array we create the following:
//
// $projects['Logo Design'][
// 'project_name' =>'Logo Design',
// 'entries' => [0 => ['comment' => 'Worked on a thing'] ] ]
//
// with the second iteration, the project name is overwritten (with same project name)
// and another comment array is added to the entries array
//
// $projects['Logo Design'][
// 'project_name' =>'Logo Design',
// 'entries' => [0 => ['comment' => 'Worked on a thing'],
// 1 => ['comment' => 'Created some stuff'] ] ]
}
// If you just did echo json_encode($projects), you would not get the format you want,
// because of the string keys. Try it without the array_values() to see what I mean.
echo json_encode(array_values($projects));

Maybe something like that?
Use project id to build target array.
while ($row = mysqli_fetch_array($result) {
if (!isset($projects[$row['id']]))
{
$projects[$row['id']] = [
'project_name' => $row['project_name'],
'entries' => [],
];
}
$projects[$row['id']]['entries'][] = [
'comment' => $row['comment'],
];
}

Related

Merge multiple object in foreach

I have one or more object in foreach and I want to merge all the objects in one in $refJSON.
$refObj = (object) array();
foreach($items as $item) { //here Im looping Two items
$refObj->refId = $item->getId();
$refObj->refLastName = $item->getLastName();
$refObj->refPhone = $item->getPhone();
$orderObj->refEmail = $item->getEmail();
}
$refJSON = json_encode($orderObj);
var_dump($refJSON);
Output :
//just the last item object
string(92) "{
"refId":"2",
"refLastName":"Joe",
"refPhone":"xxxxxxx",
"refEmail":"example#domaine.com"
}"
The output expected is to merge all the items ids 1 and 2 something like this:
[
{
"refId":"1",
"refLastName":"Steve",
"refPhone":"xxxxxxx",
"refEmail":"foo#domaine.com"
},
{
"refId":"2",
"refLastName":"Joe",
"refPhone":"xxxxxxx",
"refEmail":"example#domaine.com"
}
]
You are just overwriting the same object each time. Build each object and add this to an array (using []) and encode the result...
$refOut = array();
foreach($items as $item) { //here Im looping Two items
$refOut[] = ['refId' => $item->getId(),
'refLastName' => $item->getLastName(),
'refPhone' => $item->getPhone(),
'refEmail' => $item->getEmail()];
}
$refJSON = json_encode($refOut);

PHP turn object into array of array

I have 3 tables, after joining name and output the role with this
$encoded = array();
while($res = mysqli_fetch_assoc($result)) {
echo json_encode($res);
}
I got this
{"student_id":"1","student_name":"john","score_id":"1","score_type":"E","score_name":"England"}
{"student_id":"1","student_name":"john","score_id":"2","score_type":"B","score_name":"Brazil"}
Now I'm struggling to turn them into the format I wanted, the client site have to have this
//json
[{
"student_id":"1",
"student_name":"john",
"scores": [{
"score_id":"1",
"score_type":"E",
"score_name":"England"
},{
"score_id":"2",
"score_type":"B",
"score_name":"Brazil"
}]
}]
The challenge is it has duplicated row with the same person.
Process the output using the Array $encoded and once it is built then you can print it with JSON.
In this solution the array will be indexed by student_id and the scores by score_id. In case of student it is a must, in case of scores it is recommended:
$encoded = array();
while($res = mysqli_fetch_assoc($result)) {
// Student's details
$encoded[$res['student_id']] = array(
'student_id' => $res['student_id'],
'student_name' => $res['student_name'],
);
// Student's score details
$encoded[$res['student_id']]['scores'][$res['score_id']] = array(
'score_id' => $res['score_id'],
'score_type' => $res['score_type'],
'score_name' => $res['score_name'],
);
}
echo json_encode($encoded);
Note: this is general answer since I do not know exact structure of your data in $res.
Please find the below code to get the json format as mentioned in your question
$students = [];
$sampleData = [
[
"student_id"=>"1",
"student_name"=>"john",
"score_id"=>"1",
"score_type"=>"E",
"score_name"=>"England",
],
[
"student_id"=>"1",
"student_name"=>"john",
"score_id"=>"2",
"score_type"=>"B",
"score_name"=>"Brazil",
],
];
foreach ($sampleData as $res) {
//if student not found by id then continue
if (empty($res['student_id'])) {
continue;
}
$student = [];
//get the already exists student to add scores
if(!empty($students[$res['student_id']])) {
$student = $students[$res['student_id']];
}
//prepare the student array
$student['student_id'] = $res['student_id'];
$student['student_name'] = $res['student_name'];
$student['scores'][]['score_id'] = $res['score_id'];
$student['scores'][]['score_type'] = $res['score_type'];
$student['scores'][]['score_name'] = $res['score_name'];
$students[$res['student_id']] = $student;
}
echo json_encode(array_values($students));
hope this helps
You can find the working example here

Want to Filter an array according to value

I have a variable $a='san-serif' and an array Font_list[] now I want only the arrays whose category is 'san-serif' will be filtered. I tried a lot of codes nothing seems working here is my code:-
public function filterFont() {
$a = $_POST['key'];
$url = "https://www.googleapis.com/webfonts/v1/webfonts?key=''";
$result = json_decode(file_get_contents( $url ));
$font_list = "";
foreach ( $result->items as $font )
{
$font_list[] = [
'font_name' => $font->family,
'category' => $font->category,
'variants' => implode(', ', $font->variants),
// subsets
// version
// files
];
}
$filter = filter($font_list);
print_r(array_filter($font_list, $filter));
}
Please help me :-(
What i understood according to that you want something like below:-
<?php
$a='san-serif'; // category you want to search
$font_list=Array('0'=>Array('font_name' => "sans-sherif",'category' => "san-serif"),'1'=>Array('font_name' => "times-new-roman",'category' => "san-serif"),'2'=>Array('font_name' => "sans-sherif",'category' => "roman"));
// your original array seems something like above i mentioned
echo "<pre/>";print_r($font_list); // print original array
$filtered_data = array(); // create new array
foreach($font_list as $key=>$value){ // iterate through original array
if($value['category'] == $a){ // if array category name is equal to serach category name
$filtered_data[$key] = $value; // assign that array to newly created array
}
}
echo "<pre/>";print_r($filtered_data); // print out new array
Output:- https://eval.in/597605

Multi-array idea php

I have a PHP array thats like this:
$a1 = [
[ 'buyer'=>"ACME", 'fees1'=>"100", 'seller'=>"XYZ plc", 'fees2'=>"200", 'item'=>"Bricks" ],
[ 'buyer'=>"ACME", 'fees1'=>"110", 'seller'=>"XYZ plc", 'fees2'=>"220", 'item'=>"Bricks" ],
[ 'buyer'=>"XYZ Plc", 'fees1'=>"200", 'seller'=>"ACME", 'fees2'=>"300", 'item'=>"Cement" ],
/* and so on and on */
];
So the report I am trying to produce is this:
BRICKS---CEMENT
ACME----220------300
XYZ-----440------200
--------------------
660------500
I am out of my wits trying the best possible way to iterate it. As of now I have managed to filter out the UNIQUE buyers and sellers and items into separate arrays. Any help/tip will be much appreciated.
Thanks ahead
There's most likely a more elegant solution, but anyway
<?php
$dataset = [
[ 'buyer'=>"ACME", 'fees1'=>"100", 'seller'=>"XYZ plc", 'fees2'=>"200", 'item'=>"Bricks" ],
[ 'buyer'=>"ACME", 'fees1'=>"110", 'seller'=>"XYZ plc", 'fees2'=>"220", 'item'=>"Bricks" ],
[ 'buyer'=>"XYZ plc", 'fees1'=>"200", 'seller'=>"ACME", 'fees2'=>"300", 'item'=>"Cement" ],
/* and so on and on */
];
$columns = array_unique(array_column($dataset, 'item'));
//sort($columns);
// create a template with all possible items (as key) and value 0
$template = array_combine(
$columns,
array_pad( array(), count($columns), 0)
);
$result = [];
foreach( $dataset as $row ) {
// if we haven't seen this seller before
if ( !isset($result[ $row['seller'] ]) ) {
// create a template with all possible items but each having 0-value
$result[ $row['seller'] ] = $template;
}
// same for buyer
if ( !isset($result[ $row['buyer'] ]) ) {
$result[ $row['buyer'] ] = $template;
}
// now comes the tricky part
// remember: $result[$row['seller']] === array('Bricks'=>sumFeeBricks, 'Cemtent'=>sumFeeCement)
// i.e. $result[$row['seller']]['Cemtent'] += <something> increases sumFeeCement in the array representing the seller in $result
// $row['item'] tells you which element within $result[$row['seller']] you want to increase
// ==> $result[$row['seller']][$row['item']] += ....
// increase sumFee of the sold item by fee2 for the seller
$result[$row['seller']][ $row['item'] ] += $row['fees2'];
// increase sumFee of the sold item by fee1 for the buyer
$result[$row['buyer']][ $row['item'] ] += $row['fees1'];
}
var_export($result);
Just iterate over the array creating a new multidimensional one. No need to translate the givven array directly to the desired output.
I came with an idea of solving it, if you don't have such a function like array_column (i.e. PHP 5.4.10)
<?php
// we assume, the data is organised in such a way: first buyer/seller/whatever then fees1/fees2/etc, item can be at the end or beginning
$a1 = [
[ 'buyer'=>"ACME", 'fees1'=>"100", 'seller'=>"XYZ plc", 'fees2'=>"200", 'item'=>"Bricks" ],
[ 'buyer'=>"ACME", 'fees1'=>"110", 'seller'=>"XYZ plc", 'fees2'=>"220", 'item'=>"Bricks" ],
[ 'buyer'=>"XYZ Plc", 'fees1'=>"200", 'seller'=>"ACME", 'fees2'=>"300", 'item'=>"Cement" ],
/* and so on and on */
];
function process($obj, $arr){ // we process a single row of $a1
$data = array(); // first we create an indexed array for storing a single key and its value
foreach($obj as $key=>$val){
$key = strtolower($key);
$val = strtolower($val);
$data[] = array($key=>$val);
}
for($i=0;$i<sizeof($data);$i++){ // we iterate over this array
$key = array_pop(array_keys($data[$i])); // we've got current key
$val = $data[$i][$key]; // we've got current value, company
if(preg_match("/buyer|seller/", $key)){ // if it's seller or buyer or whatever we want just edit
$next_key = array_pop(array_keys($data[$i+1])); // we take the next element of $data which is $key=>$value, next key i.e. fees1
$next_val = $data[$i+1][$next_key]; // we take its value e.g. 100
$arr[$val]+=$next_val; // we put the money for company, and adding them up
}
}
return $arr; // the end of processing a single row of $a1
}
$data = array(); // first we create the data split into items buckets
foreach($a1 as $obj){
foreach($obj as $key=>$val){
$key = strtolower($key); // ACME or AcMe, no difference
$val = strtolower($val);
if(preg_match("/item/", $key)){
$data[$val][] = $obj;
}
}
}
print_r($data);
$final = array(); // we store the result for items
foreach($data as $item=>$obj){ // we iterate over items
$arr = array(); // variable for one item, for next we'll start from empty array
foreach($obj as $val){ // we process each row for item
$arr = process($val, $arr);
}
$final[$item] = $arr; // we put processed data to key which is item
}
$total = array(); // we store the total result
foreach($final as $val){
foreach($val as $key=>$prize){
$total[$key]+=$prize; // we add up all money for a single company
}
}
print_r($final);
print_r($total);
?>

MySQL to JSON (For use with NVD3.js)

I'm trying to export the MySQL table below:
id, asof, value
abc, 2013-06-30, 36000000
abc, 2013-12-31, 48000000
abc, 2014-01-31, 51000000
abc, 2014-02-28, 56000000
xyz, 2013-06-30, 26000000
xyz, 2013-12-31, 33000000
xyz, 2014-01-31, 33000000
xyz, 2014-02-28, 36000000
into the following json format for use in the nvd3.js charts:
[
{
"key" : "abc" ,
"values" : [ [ 2013-06-30, 36000000] , [ 2013-12-31, 48000000] , [ 2014-01-31, 51000000] , [ 2014-02-28, 56000000]
},
{
"key" : "xyz" ,
"values" : [ [ 2013-06-30, 26000000] , [ 2013-12-31, 33000000] , [ 2014-01-31, 33000000] , [ 2014-02-28, 36000000]
}
]
I'm sure this is a newbie question but I'm struggling with it. Any guidance would be much appreciated!
Edit:
I've currently been trying to use an array and while statement but have not been able to figure out how to modify the array to so that it can output to the correct json format.
$query= mysqli_query($db,"SELECT id, asof, value
FROM table;"
);
if ( ! $query) {
echo mysqli_error();
die;
}
$rows = array();
while($r = mysqli_fetch_assoc($query)) {
$rows[] = $r;
}
print json_encode($rows);
Probably the most straightforward way of doing this is simply creating a multidimensional array, filling it with data obtained from database and then using json_encode to create a JSON string, which is then sent to the client.
Here is a simple example of a function which will accept an array of items and return a JSON string in the expected format. For simplicity, it is assumed that data was is a 2D array with three columns, but you should modify it to use the format returned by a database query.
function convert($data) {
$intermediate = array();
// This intermediate steps is used just to group all rows with
// the same key
foreach($data as $item) {
list($key, $date, $value) = $item;
$intermediate[$key][] = array($date, $value);
}
$output = array();
foreach($intermediate as $key => $values) {
$output[] = array(
'key' => $key,
'values' => $values
);
}
return $output;
}
Since you're getting data from database, variable $item inside the first foreach statement might actually be an associate array, so you'll have to write something like $item['key'] to get data for columns in the current row.
If you want to use mysqli_fetch_assoc, then you might try calling the function convert in the following way:
$conn = mysqli_connect('', '', '')
$query = 'SQL you wish to execute'
$result = mysqli_query($conn, $query)
if($result) {
$jsonData = convert($result);
}
However, function itself needs a little bit changing
function convert($result) {
$intermediate = array();
while($item = mysqli_fetch_assoc($result)) {
$key = $item['id'];
$date = $item['asof'];
$value = $item['value'];
$intermediate[$key][] = array($date, $value);
}
// The rest of the function stays the same
}

Categories