Solved

Build "grouped" array from DB results

Posted on 2013-11-18
18
202 Views
Last Modified: 2013-11-28
In trying to itrerate through the results of an ExpressionEngine DB Query that returns this result:
"ProgramGroup","ProgramTitle","CourseDesc","CourseCode","CourseTtle"
"A",           "A Title",     "Z Title",   "Z",         "Z Desc"
"A",           "A Title",     "Y Title",   "Y",         "Y Desc"
"B",           "B Title",     "X Title",   "X",         "X desc"
"B",           "B Title",     "V Title",   "V",         "V desc"
"C",           "C Title",     "U Title",   "U",         "U desc"
"C",           "C Title",     "T Title",   "T",         "T desc"
"D",           "D Title",     "S Title",   "S",         "S desc"
"D",           "D Title",     "R Title",   "R",         "R desc"
"D",           "D Title",     "Q Title",   "Q",         "Q desc"

Open in new window

and build an array that will be output as JSON like below..
This is the expected output:
[{"group":"A","title":"","desc":"A Title","programs":[{"code":"Z","title":"Z Title","desc":"Z Desc"},
                                                      {"code":"Y","title":"Y Title","desc":"Y Desc"}]},
 {"group":"B","title":"","desc":"B Title","programs":[{"code":"X","title":"X Title","desc":"X Desc"},
                                                      {"code":"V","title":"W Title","desc":"W Desc"}]},
 {"group":"C","title":"","desc":"C Title","programs":[{"code":"U","title":"U Title","desc":"U Desc"},
                                                      {"code":"T","title":"T Title","desc":"T Desc"}]},
 {"group":"D","title":"","desc":"D Title","programs":[{"code":"S","title":"S Title","desc":"S Desc"},
                                                      {"code":"R","title":"R Title","desc":"R Desc"},
                                                      {"code":"Q","title":"Q Title","desc":"Q Desc"}]}]

Open in new window


This is my first try and it is not returning expected results.
$results = $this->EE->db->query($sql);
$program_group = "";
if($results->num_rows() > 0) {
    foreach($results->result_array() as $row) {
        if($program_group != $row["ProgramGroup"]) {
            $content["group"] = $row["ProgramGroup"];
            $content["title"] = "";
            $content["desc"]  = $row["ProgramTitle"];
            $program_group    = $row["ProgramGroup"];
        } else {                
            $content[$row["ProgramGroup"]]["programs"]["code"]  = $row["CourseCode"];
            $content[$row["ProgramGroup"]]["programs"]["title"] = $row["CourseTtle"];
            $content[$row["ProgramGroup"]]["programs"]["desc"]  = $row["CourseDesc"];
        }
    }
}

Open in new window

0
Comment
Question by:EddieShipman
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
18 Comments
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39657780
What have you got in $sql?
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39657819
it doesn't matter, Ray, as I'm showing the results.
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39657871
Yes, it does matter since the query can be used to build a sensible results set.  I kind of think I know what I'm asking for here :-)

Please post the query in $sql

Please add echo '<pre>';var_dump($results); after line 1 and post the output in the code snippet.

I think these comments interpret the data as I understand it now.  If this doesn't make sense, please help me get to the right structure.

<?php // RAY_temp_eddieshipman.php
error_reporting(E_ALL);

/** http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28297469.html#a39657780
 * "ProgramGroup","ProgramTitle","CourseDesc","CourseCode","CourseTtle"
 * "A",           "A Title",     "Z Title",   "Z",         "Z Desc"
 * "A",           "A Title",     "Y Title",   "Y",         "Y Desc"
 * "B",           "B Title",     "X Title",   "X",         "X desc"
 * "B",           "B Title",     "V Title",   "V",         "V desc"
 * "C",           "C Title",     "U Title",   "U",         "U desc"
 * "C",           "C Title",     "T Title",   "T",         "T desc"
 * "D",           "D Title",     "S Title",   "S",         "S desc"
 * "D",           "D Title",     "R Title",   "R",         "R desc"
 * "D",           "D Title",     "Q Title",   "Q",         "Q desc"
 *
 * [{"group":"A","title":"","desc":"A Title","programs":[{"code":"Z","title":"Z Title","desc":"Z Desc"},{"code":"Y","title":"Y Title","desc":"Y Desc"}]},
 * {"group":"B","title":"","desc":"B Title","programs":[{"code":"X","title":"X Title","desc":"X Desc"},{"code":"V","title":"W Title","desc":"W Desc"}]},
 * {"group":"C","title":"","desc":"C Title","programs":[{"code":"U","title":"U Title","desc":"U Desc"},{"code":"T","title":"T Title","desc":"T Desc"}]},
 * {"group":"D","title":"","desc":"D Title","programs":[{"code":"S","title":"S Title","desc":"S Desc"},{"code":"R","title":"R Title","desc":"R Desc"},{"code":"Q","title":"Q Title","desc":"Q Desc"}]}]
 */

/** LOOKS LIKE THESE ARE THE VARS IN EACH OBJECT
 * {"group":ProgramGroup, "title":NULL, "desc":ProgramTitle, "programs": array
 *   ( { "code":CourseCode, "title":CourseDesc, "desc":CourseTtle }
 *   , { "code":CourseCode, "title":CourseDesc, "desc":CourseTtle }
 *   , ...etc...
 *   )
 * }
 *
 * JSON OBJECTS ARE DELIMITED WITH {} AND ARRAYS WITH []
 */

Open in new window

Standing by, ~Ray
0
Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

 
LVL 26

Author Comment

by:EddieShipman
ID: 39657875
I don't expect you to know what these fields are in the ExpressionEngine tables but this is how we have our channels setup. This is the sql run in the query() call:

SELECT d2.field_id_12 as ProgramGroup, 
       d2.field_id_23 as ProgramTitle, 
       TRIM(t.title) as CourseDesc, 
       TRIM(d.field_id_14) as CourseCode, 
       TRIM(t.url_title) as CourseTitle
FROM channel_data d
JOIN channel_titles t ON d.entry_id = t.entry_id
JOIN relationships r on r.parent_id = d.entry_id
JOIN channel_data d2 ON d2.entry_id = r.child_id
WHERE d.field_id_14 != '' 
GROUP BY ProgramGroup, CourseCode

Open in new window

0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39657892
Put vardump($results) after getting the results and then also for each row in the foreach.
output is here: http://www.scic.com/files/eddie/results.txt
It contains actual data.

BTW...
"LOOKS LIKE THESE ARE THE VARS IN EACH OBJECT"
Yes your assumptions about the output are correct.

"JSON OBJECTS ARE DELIMITED WITH {} AND ARRAYS WITH []"

Yes, the desired output would be json_encoded().
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39657969
Yeah, it looks like there will be some programming needed to transform the results set into the object / array elements that can be used with JSON_Encode() to produce the outputs.  I don't recognize the format of the scic.com data as PHP var_dump() output, but I can probably still work with it.
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39657972
It is ExpressionEngine result set objects that were being dumped. Thanks.
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39658000
OK, thanks.  I was looking for var_dump($results) so I could see the entire data construct.  I'll see what I can do with the information I have, but if you can help by giving me what I asked for it would probably lead to a faster and more accurate answer.
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39658247
It is the first section in the text file at the link I posted.
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39658269
I know you honestly think your posts are "good enough" to respond to my requests for assistance, but there is a great precision needed to be successful in computer science.  Experienced programmers understand and expect a "signature" output from var_dump(), which is a built-in PHP function with a predictable and consistently formatted output.  Part of the reason we want to see these predictable outputs is because we know what to do with the data.   I'll look at this again tomorrow as time permits.  If you can help speed this along by posting the information I asked for it will help me to help you.

Please read the man page at var_dump() and see if you can use the function to produce the output we need to move forward, thanks.
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39658286
Ray, I'm not trying to be misleading at all. I understand the "precision" needed here and honestly, that it just the copied output that is showing in all my browsers when I view source with the results showing.

This was the code that produced the output in the text file, I believe it must have something to do with my PHP version because it looks the same in 3 different browsers.
$results = $this->EE->db->query($sql);
$program_group = "";
echo "Results:<br />";
var_dump($results);
if($results->num_rows() > 0) {
    foreach($results->result_array() as $row) {
echo "<br /><br />Results:<br />";
var_dump($row);
        if($program_group != $row["ProgramGroup"]) {
            $content["group"] = $row["ProgramGroup"];
            $content["title"] = "";
            $content["desc"]  = $row["ProgramTitle"];
            $program_group    = $row["ProgramGroup"];
        } else {                
            $content[$row["ProgramGroup"]]["programs"]["code"]  = $row["CourseCode"];
            $content[$row["ProgramGroup"]]["programs"]["title"] = $row["CourseTtle"];
            $content[$row["ProgramGroup"]]["programs"]["desc"]  = $row["CourseDesc"];
        }
    }
}

Open in new window

Here's a screenshot of the outpiut:
var_dump() screenshotSo, I modified it to this and the results.text file has been updated with this output.
I only included 25 rows in the new output because I think it should be enough. If you want more, let me know.
$results = $this->EE->db->query($sql);
$program_group = "";
echo "Results:<br />";
print_r($results);
if($results->num_rows() > 0) {
    foreach($results->result_array() as $row) {
echo "<br /><br />Results:<br />";
print_r($row);
        if($program_group != $row["ProgramGroup"]) {
            $content["group"] = $row["ProgramGroup"];
            $content["title"] = "";
            $content["desc"]  = $row["ProgramTitle"];
            $program_group    = $row["ProgramGroup"];
        } else {                
            $content[$row["ProgramGroup"]]["programs"]["code"]  = $row["CourseCode"];
            $content[$row["ProgramGroup"]]["programs"]["title"] = $row["CourseTtle"];
            $content[$row["ProgramGroup"]]["programs"]["desc"]  = $row["CourseDesc"];
        }
    }
}

Open in new window

0
 
LVL 11

Expert Comment

by:SAMIR BHOGAYTA
ID: 39659107
hi..
I solved this by comparing an imploded string from the arrays with GROUP_CONCAT on the table. Since you can't normally use GROUP_CONCAT in the WHERE clause I had to do a workaround with the FROM clause.

<?php
    $s = '';
    foreach($updated as $u){
        $s .= $u['pId'] . $u['name'] . 'updated,';
    }
    foreach($deleted as $d){
        $s .= $d['pId'] . $d['name'] . 'deleted,';
    }
    foreach($added as $a){
        $s .= $a['pId'] . $a['name'] . 'added,';
    }

    //remove last comma
    $s = rtrim($s, ',');

    $stmt = $mysqli -> prepare("
    SELECT
        relationId
        FROM (
            SELECT
                relationId,
                GROUP_CONCAT(pId, name, changeType ORDER BY changeType DESC, id ASC) AS personConcat
            FROM
                persons
            GROUP BY relationId
        ) x
        WHERE personConcat = ?
    ");

    $stmt -> bind_param('s', $s);
    $stmt -> execute();
?>
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39659449
Samir,
I think you posted an answer to the wrong question.
0
 
LVL 26

Accepted Solution

by:
EddieShipman earned 0 total points
ID: 39660821
Ok, Ray, I think we've got it. Check this out:
$results = $this->EE->db->query($sql);
$program_group = "";
if($results->num_rows() > 0) {
	$firstrow = array_shift(array_values($results->result_array()));
	$content = array();
	$content["group"] = $firstrow["ProgramGroup"];
	$content["title"] = "";
	$content["desc"] = $firstrow["ProgramTitle"];
	$content["topics"] = array();
	$program_group = $firstrow["ProgramGroup"];
	foreach($results->result_array() as $row) {
		if($row["ProgramGroup"] != $program_group) {
			array_push($output, $content);
			$content = array();
			$program_group = $row["ProgramGroup"];
			$content["group"] = $row["ProgramGroup"];
			$content["title"] = "";
			$content["desc"] = $row["ProgramTitle"];
			$content["topics"] = array();
		}
		$detailcontent = array();
		$detailcontent["code"]  = $row["CourseCode"];
		$detailcontent["title"] = $row["CourseTitle"];
		$detailcontent["desc"]  = $row["CourseDesc"];
		array_push($content["topics"], $detailcontent);
	}
	array_push($output, $content);
}

Open in new window

0
 
LVL 34

Expert Comment

by:Slick812
ID: 39660868
Could not test this but this is my idea -
$program_group = "";
$cntNum = 0;
$prmNum=1;
if($results->num_rows() > 0) {
    foreach($results->result_array() as $row) {
        if($program_group != $row["ProgramGroup"]) {
            $content[$cntNum++] =array("group"=>$row["ProgramGroup"],
            "title" => '','desc' => $row["ProgramTitle"],
            "programs"=>array(array("code" => $row["CourseCode"],"title" => $row["CourseTtle"],"desc" => $row["CourseDesc"])));
            $program_group    = $row["ProgramGroup"];
            $prmNum=1;
        } else {
       $content[$cntNum]["programs"][$prmNum++]=array("code" => $row["CourseCode"],"title" => $row["CourseTtle"],"desc" => $row["CourseDesc"]);
        }
    }
}

Open in new window

the $content array should have something like
$content[0]["group"]
$content[0]['desc']
$content[0]["programs"][0]["code"]
$content[0]["programs"][0]["title"]
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 39660900
Oh, BTW, to get the correct results using the code in my last comment we modified the SQL a little:
SELECT d2.field_id_12 as ProgramGroup, 
       d2.field_id_23 as ProgramTitle, 
       TRIM(t.title) as CourseDesc, 
       TRIM(d.field_id_14) as CourseCode, 
       TRIM(t.url_title) as CourseTitle
FROM exp_channel_data d
JOIN exp_channel_titles t ON d.entry_id = t.entry_id
JOIN exp_relationships r on r.parent_id = d.entry_id
JOIN exp_channel_data d2 ON d2.entry_id = r.child_id
WHERE d.field_id_14 != '' 
GROUP BY ProgramGroup, CourseCode 
ORDER BY ProgramGroup, CourseCode

Open in new window

0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39661038
I don't think this programming will produce the JSON string posted in the second code snippet of the original question.  The original JSON string was built up from arrays of objects.  You can test this by using var_dump() to print out the resulting JSON strings, and compare them to each other.  For better or worse, PHP uses different syntax to iterate over arrays and objects; these are unlike data types.

But if you're happy with it, you can close the question by accepting your own answer.  If I get some free time tomorrow I can look at it again, but I just got busied out by paying customers today.  I guess that's a good problem!

Best regards, ~Ray
0
 
LVL 26

Author Closing Comment

by:EddieShipman
ID: 39683150
Self answered.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

628 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question