MySQL select multi dimensional? - php

I would like to select all the posts and their attachments from my database.
This is the structure with dummy data:
Posts table
id | post | userId |
---------|---------------|----------|
1 | "hello" | 1 |
2 | "world" | 1 |
3 | "ouch" | 2 |
4 | "test" | 1 |
Attachments table
id | postId | fileName | time |
---------|---------------|----------|----------|
1 | 1 |"hey.jpg" | 0 |
2 | 1 |"test.png"| 53252354 |
3 | 2 |"asd.png" | 0 |
4 | 4 |"asd2.png"| 0 |
My code looks like this so far, but I doesn't really get what I'd like to.
$qry = $db->prepare('
SELECT p.id
, p.post
, p.userId
, att.fileName
, att.time
FROM posts p
LEFT
JOIN attachments att
ON att.postId = p.id
');
$qry->execute();
$postsArray = $qry->fetchAll(PDO::FETCH_ASSOC);
I would like to have something like this:
[{'id': 1,
'post': 'hello',
'userId': 1,
'attachments': [{'fileName': 'hey.jpg', 'time:' 0}, ... ]
}, ... ]
How could I achieve this?

Your query will give you the right data for the results you want, you can post-process in PHP to get the format you want:
foreach ($postArray as $post) {
$fixed_part = array('id' => $post['id'], 'post' => $post['post'], 'userId' => $post['userId']);
$key = serialize($fixed_part);
if (!isset($out[$key])) $out[$key] = $fixed_part;
$out[$key]['attachments'][] = array('fileName' => $post['fileName'], 'time' => $post['time']);
}
$out = array_values($out);
echo json_encode($out, JSON_PRETTY_PRINT);
Output is too long to post but can be seen in this demo. Query results can be seen on dbfiddle.

Usually I would do something like this:
$result = $db->query("select id, post, userId from posts");
$posts = [];
while ($post = $result->fetch(PDO::FETCH_OBJECT)) {
$post->attachments = [];
$posts[$post->id] = $post;
}
$result = $db->query("select postId, fileName, time from attachments");
while ($att = $result->fetch(PDO::FETCH_OBJECT)) {
$posts[$att->postId]->attachments[] = $att;
unset($att->postId); // optional
}
$posts = array_values($posts); // optional
echo json_encode($posts);
Note that the $posts array is id-indexed. I would keep it that way. But if you need exactly the same result as in your question (zero-indexed), you can add this line:
$posts = array_values($posts);
In newer MySQL versions you can also get the JSON result with a single SQL query:
select json_arrayagg(post_json) as json
from (
select json_object(
'id', p.id,
'post', p.post,
'userId', p.userId,
'attachments', json_arrayagg(
json_object('fileName', a.fileName, 'time', time)
)
) as post_json
from posts p
left join attachments a on a.postId = p.id
group by p.id
) x
Result:
[{"id": 1, "post": "hello", "userId": 1, "attachments": [{"time": 0, "fileName": "hey.jpg"}, {"time": 53252354, "fileName": "test.png"}]}, {"id": 2, "post": "world", "userId": 1, "attachments": [{"time": 0, "fileName": "asd.png"}]}, {"id": 3, "post": "ouch", "userId": 2, "attachments": [{"time": null, "fileName": null}]}, {"id": 4, "post": "test", "userId": 1, "attachments": [{"time": 0, "fileName": "asd2.png"}]}]
db-fiddle demo

Related

concat two mysql tables and convert it to json with php

I'm using PHP with PDO for a project
I have the following two tables in my database.
Category
CategoryID | Name | CategoryCode
1 | Fixed | FA
2 | Consumable | CA
3 | Intangible | IA
Type
TypeID | CategoryID | Name | TypeCode
1 | 1 | Furniture | FU
2 | 1 | Computers & Computer Peripherals | CP
3 | 1 | Electrical Appliances | EA
4 | 1 | Machinery | MA
5 | 2 | Computer Peripherals | PE
6 | 3 | Software | SW
I need to get a output like below from the select operation. I have tried it with group concat and then fecthAll(), but it doesn't give me the result in correct JSON
Output
[
{
"CategoryID": 1,
"Name": "Fixed",
"CategoryCode": "FA",
"Types": [
{
"TypeID": 1,
"Name": "Furniture",
"TypeCode": "FU"
},
{
"TypeID": 2,
"Name": "Computers & Computer Peripherals",
"TypeCode": "CP"
},
{
"TypeID": 3,
"Name": "Electrical Appliances",
"TypeCode": "EA"
}
]
},
{
"CategoryID": 2,
"Name": "Consumable",
"CategoryCode": "CA",
"Types": [
{
"TypeID": 5,
"Name": "Computer Peripherals",
"TypeCode": "PE"
}
]
}
]
Figured it out this way to get my intended output
protected function getCategories(){
$dbConnection = $this->connect();
$catSql = 'SELECT * FROM `category`';
$stmt = $dbConnection->prepare($catSql);
$stmt->execute();
$result = $stmt->fetchAll();
$output = array();
foreach ($result as $row) {
$line = array("CategoryID" => $row['CategoryID'], "CategoryName" => $row['Name'], "CategoryCode" => $row['CategoryCode']);
$typeSQL = 'SELECT
TypeID,
Name,
TypeCode
FROM type
WHERE
CategoryID = ' . $row['CategoryID'];
$stmt2 = $dbConnection->prepare($typeSQL);
$stmt2->execute();
$types = $stmt2->fetchAll();
$typeArray = array();
foreach ($types as $type) {
$typeLine = array("TypeID" => $type['TypeID'], "TypeName" => $type['Name'], "TypeCode" => $type['TypeCode']);
array_push($typeArray, $typeLine);
}
$line['Types'] = $typeArray;
array_push($output, $line);
}
return json_encode($output);
}

How to join two MySQL tables for wp_rest_api

In my WordPress database I have three tables wp_companies which stores some company info and wp_product_types which stores a bunch of product types that a company can assign them selves then I have wp_company_products which is used to assign product types to a company using ids.
Heres an example of how the database looks:
wp_companies
id | company_name | member_type | logo
-----------------------------------------------------------------
1 | Google | full | https://via.placeholder.com/150
-----------------------------------------------------------------
2 | Crunchyroll | full | https://via.placeholder.com/150
wp_products
id | product_name |
----------------------
1 | Car Insurance |
----------------------
2 | House Insurance |
----------------------
3 | Life Insurance |
wp_company_products
id | company_id | product_id
----------------------------
1 | 1 | 2
----------------------------
2 | 2 | 1
----------------------------
3 | 1 | 3
Here's my current MySQL query that simply shows the data in wp_companies
add_action('rest_api_init', function() {
register_rest_route('custom-routes/v1', 'members', array(
'methods' => 'GET',
'callback' => 'get_members'
) );
});
function get_members($data) {
global $wpdb;
$query = $wpdb->get_results( "SELECT company_name, member_type, logo, site_url FROM {$wpdb->prefix}companies ORDER BY RAND()" );
foreach ( $query as $member ) {
$member_data[] = array(
"company_name" => $member->company_name,
"member_type" => $member->member_type,
"logo" => $member->logo,
);
}
return $member_data;
}
This displays my data like so on my api end point:
[
{
"company_name":"Google",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
},
{
"company_name":"Crunchyroll",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
}
]
But what I want is to combine the wp_companies and wp_company_products tables so that my data is displayed something like this on the api end point:
[
{
"company_name":"Google",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
"products": [
"House Insurance",
"Life Insurance"
]
},
{
"company_name":"Crunchyroll",
"member_type":"full",
"logo":"https://via.placeholder.com/150",
"products": [
"Car Insurance",
]
}
]
How can I structure my MySQL query to be able to achieve this?
Please try this
function get_members($data) {
global $wpdb;
$query = $wpdb->get_results( "SELECT company_name, member_type, logo, site_url FROM {$wpdb->prefix}companies ORDER BY RAND()" );
foreach ( $query as $member ) {
$productQuery = $wpdb->get_results( "SELECT product_name FROM wp_products WHERE id IN (SELECT product_id from wp_company_products WHERE compony_id = '{$member->id}') " );
$products = array();
foreach ( $productQuery as $prduct ) {
array_push($products ,$prduct->product_name);
}
$member_data[] = array(
"company_name" => $member->company_name,
"member_type" => $member->member_type,
"logo" => $member->logo,
"products" => $products
);
}
return $member_data;
}

Creating hierarchical JSON from MySQL results and PHP for D3.js tree?

I am trying to create the following JSON (much simplified...) from database results using PHP:
{
"name": "Bob",
"children": [{
"name": "Ted",
"children": [{
"name": "Fred"
}]
},
{
"name": "Carol",
"children": [{
"name": "Harry"
}]
},
{
"name": "Alice",
"children": [{
"name": "Mary"
}]
}
]
}
The database tables:
Table 'level_1':
level_1_pk| level_1_name
-------------------------
1 | Bob
Table 'level_2':
level_2_pk| level_2_name | level_1_fk
-------------------------
1 | Ted | 1
2 | Carol | 1
3 | Alice | 1
Table 'level_3':
level_3_pk| level_3_name | level_2_fk
-------------------------
1 | Fred | 1
2 | Harry | 2
3 | Mary | 3
The code:
$query = "SELECT *
FROM level_1
LEFT JOIN level_2
ON level_1.level_1_pk = level_2.level_1_fk";
$result = $connection->query($query);
while ($row = mysqli_fetch_assoc($result)){
$data[$row['level_1_name']] [] = array(
"name" => $row['level_2_name']
);
}
echo json_encode($data);
Produces:
{"Bob":[{"name":"Ted"},{"name":"Carol"},{"name":"Alice"}]}
Question:
How can I get the next level, level_3, and include the text "children" and level_3 children in the JSON as required in the JSON defined above?
I imagine I will need the PHP to be recursive given more children in the JSON.
SQL
This doesn't look like a decent design for hierarchical data. Consider another approach like adjacency list.
Solution #1 - MySQL 8 JSON support:
With MySQL 8 you can use JSON_ARRAYAGG() and JSON_OBJECT() to get the JSON result with SQL only:
select json_object(
'name', l1.level_1_name,
'children', json_arrayagg(json_object('name', l2.level_2_name, 'children', l2.children))
) as json
from level_1 l1
left join (
select l2.level_2_name
, l2.level_1_fk
, json_arrayagg(json_object('name', l3.level_3_name)) as children
from level_2 l2
left join level_3 l3 on l3.level_2_fk = l2.level_2_pk
group by l2.level_2_pk
) l2 on l2.level_1_fk = l1.level_1_pk
group by level_1_pk
The result is:
{"name": "Bob", "children": [{"name": "Ted", "children": [{"name": "Fred"}]}, {"name": "Carol", "children": [{"name": "Harry"}]}, {"name": "Alice", "children": [{"name": "Mary"}]}]}
db-fiddle demo
Formatted:
{
"name": "Bob",
"children": [
{
"name": "Ted",
"children": [
{
"name": "Fred"
}
]
},
{
"name": "Carol",
"children": [
{
"name": "Harry"
}
]
},
{
"name": "Alice",
"children": [
{
"name": "Mary"
}
]
}
]
}
Solution #2 - Constructing JSON with GROUP_CONCAT():
If the names don't contain any quote carachters, you can manually construct the JSON string in older versions using GROUP_CONCAT():
$query = <<<MySQL
select concat('{',
'"name": ', '"', l1.level_1_name, '", ',
'"children": ', '[', group_concat(
'{',
'"name": ', '"', l2.level_2_name, '", ',
'"children": ', '[', l2.children, ']',
'}'
separator ', '), ']'
'}') as json
from level_1 l1
left join (
select l2.level_2_name
, l2.level_1_fk
, group_concat('{', '"name": ', '"', l3.level_3_name, '"', '}') as children
from level_2 l2
left join level_3 l3 on l3.level_2_fk = l2.level_2_pk
group by l2.level_2_pk
) l2 on l2.level_1_fk = l1.level_1_pk
group by level_1_pk
MySQL;
The result would be the same (see demo)
Solution #3 - Constructing nestet structure with PHP objects:
You can also write a simpler SQL query and construct the nested structure in PHP:
$result = $connection->query("
select level_1_name as name, null as parent
from level_1
union all
select l2.level_2_name as name, l1.level_1_name as parent
from level_2 l2
join level_1 l1 on l1.level_1_pk = l2.level_1_fk
union all
select l3.level_3_name as name, l2.level_2_name as parent
from level_3 l3
join level_2 l2 on l2.level_2_pk = l3.level_2_fk
");
The result is
name | parent
----------------
Bob | null
Ted | Bob
Carol | Bob
Alice | Bob
Fred | Ted
Harry | Carol
Mary | Alice
demo
Note: The name should be unique along all tables. But I don't know what result you would expect, if duplicates were possible.
Now save the rows as objects in an array indexed by the name:
$data = []
while ($row = $result->fetch_object()) {
$data[$row->name] = $row;
}
$data will now contain
[
'Bob' => (object)['name' => 'Bob', 'parent' => NULL],
'Ted' => (object)['name' => 'Ted', 'parent' => 'Bob'],
'Carol' => (object)['name' => 'Carol', 'parent' => 'Bob'],
'Alice' => (object)['name' => 'Alice', 'parent' => 'Bob'],
'Fred' => (object)['name' => 'Fred', 'parent' => 'Ted'],
'Harry' => (object)['name' => 'Harry', 'parent' => 'Carol'],
'Mary' => (object)['name' => 'Mary', 'parent' => 'Alice'],
]
We can now link the nodes in a single loop:
$roots = [];
foreach ($data as $row) {
if ($row->parent === null) {
$roots[] = $row;
} else {
$data[$row->parent]->children[] = $row;
}
unset($row->parent);
}
echo json_encode($roots[0], JSON_PRETTY_PRINT);
The result:
{
"name": "Bob",
"children": [
{
"name": "Ted",
"children": [
{
"name": "Fred"
}
]
},
{
"name": "Carol",
"children": [
{
"name": "Harry"
}
]
},
{
"name": "Alice",
"children": [
{
"name": "Mary"
}
]
}
]
}
demo
If multiple root nodes are possible (multiple rows in level_1_name), then use
json_encode($roots);
I will recommend the following recursive:
function getPeople($levelNum = 1, $parent = 0) {
if ($levelNum > 3) return array(); // break recursion condition
global $connection;
$level = 'level_' . $levelNum; // also can check here if the table exist by this name
$query = "SELECT * FROM ". $level;
if ($parent) // if there is parent add him to query
$query .= "WHERE " . $level . "_fk = " . $parent;
$result = $connection->query($query);
while ($row = mysqli_fetch_assoc($result)) { // for each row:
$idCol = $level . "_pk"; // get the primary ID key
$id = $row[$idCol]; // get the ID
$localResult[$id] = array("Name" => $row[$level . "_name"]); // set local array with key as ID and name
}
foreach ($localResult as $id => $elem) { // elem is array with only name
$children = getPeople($levelNum + 1, $id); // recursively get all children
if ($children)
$elem["children"] = $children;
$data[] = $elem; // append the new elem to origin array
}
return $data;
}
Initial call should be like getPeople() or json_encode(getPeople());
Notice - I used max depth as recursive break assuming you know max depth - you can also (and I recommend you do) skip the break condition and just check if the table name exist ! (as $level string)
I wrote it as pseudo code as I didn't actually build the table - it may have syntax error but the logic should be solid...

JSON Formatting from SQL via PHP

I'm trying to create a datatable that groups items based on a column name. In order to populate the table correctly I need to format the JSON with parent and child relationships but am having troubles. I'll be grabbing the data from MSSQL via PHP.
+---------------+-------+--------------+------------+------------+--------+
| ACTIVITY_NAME | GROUP | START_DATE | END_DATE | COMPLETED | TOTAL |
+---------------+-------+--------------+------------+------------+--------+
| Test | 1 | 04/30/2015 | 05/01/2015| 10 | 15 |
| Test | 2 | 04/30/2015 | 05/01/2015| 20 | 25 |
| Test2 | 1 | 05/2/2015 | 05/03/2015| 30 | 35 |
| Test2 | 2 | 05/2/2015 | 05/03/2015| 40 | 45 |
| Test2 | 3 | 05/2/2015 | 05/03/2015| 50 | 55 |
+---------------+-------+--------------+------------+------------+--------+
I need the JSON formatted like this with the parent objects being under the "data" and the children being under the "children". I'm having a hard time figuring out if I need to do two seperate queries, one for the rollup data in the parent and the second for the child rows. Any help would be appriecated.
Edit to add PHP:
<?php
include("connect.php");
if( $conn === false ) {
echo "Could not connect.\n";
die( print_r( sqlsrv_errors(), true));
}
/* Set up and execute the query. */
$sql = "<QUERY>";
$stmt = sqlsrv_query( $conn, $sql);
do {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$json[] = $row;
}
} while ( sqlsrv_next_result($stmt) );
foreach ($json as $result) {
$data[$result['ACTIVITY_NAME']]['children'] = $result;
}
echo json_encode($data);
?>
I need this format:
JSON blob: https://jsonblob.com/554b958be4b05c281ae9707e
{
"data": [
{
"ACTIVITY_NAME": "Test",
"children": [
{
"ACTIVITY_NAME": "Test",
"MAINTENANCE_GROUP": "1",
"START_DATE": "04/30/2015",
"END_DATE": "05/01/2015",
"COMPLETED": "10",
"TOTAL": "15"
},
{
"ACTIVITY_NAME": "Test",
"MAINTENANCE_GROUP": "2",
"START_DATE": "04/30/2015",
"END_DATE": "05/01/2015",
"COMPLETED": "20",
"TOTAL": "25"
}
]
},
{
"ACTIVITY_NAME": "Test2",
"children": [
{
"ACTIVITY_NAME": "Test2",
"MAINTENANCE_GROUP": "1",
"START_DATE": "05/2/2015",
"END_DATE": "05/03/2015",
"COMPLETED": "30",
"TOTAL": "35"
},
{
"ACTIVITY_NAME": "Test2",
"MAINTENANCE_GROUP": "1",
"START_DATE": "05/2/2015",
"END_DATE": "05/03/2015",
"COMPLETED": "40",
"TOTAL": "45"
},
{
"ACTIVITY_NAME": "Test2",
"MAINTENANCE_GROUP": "1",
"START_DATE": "05/2/2015",
"END_DATE": "05/03/2015",
"COMPLETED": "50",
"TOTAL": "55"
}
]
}
]
}
I will recommend you to use two queries, then put the data in an array that matches your format and json_encode it to produce the required result.
You may want to take a look at SQL Server recursive query
It seems that you are grouping by ACTIVITY_NAME, if that's the case and you don't want to make additional queries, you can first make an associative array:
foreach ($results as $result) {
$data[$result['ACTIVITY_NAME']]['children'] = $result;
}
Then you could use that array to iterate over the children to calculate data like MAINTENANCE_GROUP, COMPLETED and TOTAL;
After you've done all this, you can then use array_values to get a non-associative array.
Here is what the working script looks like:
<?php
include("connect.php");
if( $conn === false ) {
echo "Could not connect.\n";
die( print_r( sqlsrv_errors(), true));
}
/* Set up and execute the query. */
$sql = "<query> ";
$stmt = sqlsrv_query($conn, $sql);
// This is where the data will be organized.
// It's better to always initialize the array variables before putting data in them
$data = array();
// Get the rows one by one
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
// Extract the activity name; we want to group the rows by it
$name = $row['ACTIVITY_NAME'];
$group = '';
$sdate = '';
$edate = '';
$completed = '';
$total = '';
$perc = '';
// Check if this activity was encountered before
if (! isset($data[$name])) {
// No, this is the first time; we will make room for it, first
$data[$name] = array(
// Remember the name
'ACTIVITY_NAME' => $name,
'MAINTENANCE_GROUP' => $group,
'START_DATE' => $sdate,
'END_DATE' => $edate,
'COMPLETED' => $completed,
'TOTAL_CLUSTERS' => $total,
'COMPLETE_PERC' => $perc,
// No children yet
'children' => array(),
);
}
// Put the row into the list of children for this activity
$data[$name]['children'][] = $row;
}
// Here, the entries in $data are indexed by the values they also have in 'ACTIVITY_NAME'
// If you want them numerically indexed, all you have to do is:
$data = array_values($data);
echo json_encode(array('data' => $data));
//echo json_encode($data);
?>

Complicated nested array issue

I want to query data from a database into a json array that ultimalty produces a force directed graph in javascript. Here is what the Json array should be like. However nodes can have mulitiple adjacencies or none, how can I query a json array where the adjacencies section varies from node to node and is able to adjust according to the number of adjacencies a node has?
Var JSON =[
{
"adjacencies": [
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
}
],
"data": {
"$color": "#416D9C",
"$type": "star"
},
"id": "graphnode5",
"name": "graphnode5"
},
];
or they can have
Var JSON =[
{
"adjacencies": [
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
},
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
},
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
}
],
"data": {
"$color": "#416D9C",
"$type": "star"
},
"id": "graphnode5",
"name": "graphnode5"
},
];
or they can not have any
Var JSON =[
{
"adjacencies": [],
"data": {
"$color": "#416D9C",
"$type": "star"
},
"id": "graphnode5",
"name": "graphnode5"
},
];
Here is my attempt so far, however this only produces a json that only allows one adjacencies, How can I setup a Json query that will adjust the the number of adjacencies a node have? while just loading the data and id section once but allowing the adjacenies to be varied?
Here is my Database structure
nodes Relationships
----- -------------
id int(11), id int(11),
name varchar(35), goingto int(11), //this is the destination node from the id relation
color varchar(7), data varchar(0) null
type varchar (12), Foreign key (id) references nodes(id)
Primary key (id)
engine = innodb
And here is my attempt that
function getjson(){
$db = adodbConnect();
$query = "SELECT nodes.*, relationships.* FROM nodes inner JOIN relationships ON nodes.id = relationships.id";
$result = $db -> Execute($query);
while($row=$result->FetchRow())
{
$id= (float)$row['id'];
$name = $row['name'];
$color1 = $row['color'];
$type1 = $row['type'];
$to= (float)$row['goingto'];
$thumb =$row['thumb']; //image path
$array[] = array(
"adjacencies" => array( array(
"nodeTo" => "$to",
"nodeFrom" => "$id",
"data" => array() )),
"data" => array(
"$"."color" => $color1,
"$"."type" => $type1 ),
"id" => $id,
"name" => "<img src='".$thumb."' height='25' width='25' alt='root'/><label>".$name."</label>");
}
$json = json_encode($array);
print "$json";
//return $json;
}
If you want to return the result in a single query, then you will end up with duplicated data for the node, in each separate row where there's a distinct adjacency from that node... Which is fine, that's how it works.
But as it sits, you won't get nodes returned if there's no adjacency on that node (because you're using an INNER join. You should use a LEFT join to include nodes that have no results from the related adjacency table).
By sorting by node id, we explicitly ensure that all nodes and their adjacencies appear grouped together. This is probably happening already because id is your pk and hence the sort is happening this way "automatically". But an ORDER BY nodes.id ensures this happens, and makes your intention clear to anyone looking at the code.
Also, because you're returning everything * from both tables, you're going to have column name conflicts, on node.id and relationship.id. Ideally you'd explicitly name your columns to avoid this so that you have predictable results back in PHP.
So your SQL could look more like:
SELECT
n.id as n_id,
n.name,
n.color,
n.type,
r.id as r_id,
r.goingto,
r.data
FROM
nodes n
LEFT JOIN relationships r
ON n.id = r.id
ORDER BY
n.id
This returns a result set that looks something like:
n_id | name | color | type | r_id | goingto | data
------+-------+--------+-------+------+---------+-----------
1 | node1 | red | type1 | 1 | 5 | stuff
1 | node1 | red | type1 | 2 | 6 | morestuff
2 | node2 | blue | type2 | 3 | 10 | whatever
3 | node3 | green | type3 | null | null | null
4 | node4 | orange | type4 | 4 | 20 | xxx1
4 | node4 | orange | type4 | 5 | 21 | xxx2
4 | node4 | orange | type4 | 6 | 22 | xxx3
etc...
(ie this assumes node 1 has two relationships, node 2 has 1 relationship, node 3 has no relationships, and node 4 has 3).
And then, your code that builds the array just needs to iterate the results, building a new node only when the current record's node is not the same as the previous one (ie we're relying on the ORDER BY node.id to "gather" all the info for a particular node, sequentially).
This code hasn't been tested, but I think the intent is clear, you should be able to bend this as required - but it basically just implements the above.
Replace your while loop with all of this.
$previd = -1;
while($row=$result->FetchRow())
{
$id= (float)$row['n_id']; // <--- note change from 'id' to 'n_id'
$name = $row['name'];
$color1 = $row['color'];
$type1 = $row['type'];
$to= (float)$row['goingto'];
$thumb =$row['thumb']; //image path
// Is this row the start of a new node?
if ($previd != $id) {
// Yes, new node. Record our new node id, for future new node checks.
$previd = $id;
// Store the previous node we've already built, now that it's complete (but only if there was a previous node!)
if ($previd != -1) {
$array.push($node);
}
// Start our new node off, ready to accept adjacencies
$node = array(
"adjacencies" => array(),
"data" => array(
"$"."color" => $color1,
"$"."type" => $type1
),
"id" => $id,
"name" => "<img src='".$thumb."' height='25' width='25' alt='root'/><label>".$name."</label>");
}
// Any adjacency for this node, on this row?
if ($to != null) { // <-- Not sure about this line!
// Yes there is, so create the new adjacency record and add it to the current node's adjacency array.
$node["adjacencies"].push(
array(
"nodeTo" => "$to",
"nodeFrom" => "$id",
"data" => array()
)
);
}
}
I'm not sure how "no adjacency" will be represented in $to - ie if this will be "null" or what. I'll leave that to you to test, but suffice to say you'll need to reflect this in the line if ($to != null) { // <-- Not sure about this line!

Categories