I created a D3 graph which works with an local JSON file. Now I want to utilize a MySQL DB, where I wrote a PHP script to fetch the data. The script is working but I receive a parsing error, as soon as I feed my D3 graph with it.
I am pretty new in terms of DB and PHP handling. I guess my Javascript file can´t resolve the PHP result proper, as the local JSON file starts with "nodes"... instead of "0".
How can I resolve that?
The JSON file looks like:
{
 "nodes": [
  { "id": 0, "type": "food" },
  { "id": 1, "type": "drinks" },
  { "id": 2, "type": "snacks" }
 ]
}
The PHP script and output:
<?php
$username = "root"; 
$password = "root";   
$host = "localhost";
$database="idep3";
$connection = mysqli_connect($host, $username, $password, $database);
$connection2 = mysqli_select_db($connection, $database);
$myquery = "
SELECT * FROM idep3.nodes";
$query = mysqli_query($connection, $myquery);
if ( ! $query ) {
    echo mysql_error();
    die;
}
$data = array();
for ($x = 0; $x < mysqli_num_rows($query); $x++) {
    $data[] = mysqli_fetch_assoc($query);
}
echo json_encode($data, JSON_FORCE_OBJECT);     
 
mysqli_close($connection);
?>
Output:
 {"0":{"id":"0","type":"food"},"1":{"id":"1","type":"drinks"},"2":{"id":"2","type":"snacks"}}
And finally the graph:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>D3v6 DB demo</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<style>
    body {
        background-color: #e6e7ee;
    }
    circle {
        stroke: black;
        stroke-width: 1px;
        cursor: pointer;
    }
</style>
<body>
    <script>       
        const data = "connection.php";
        const onLoad = graph => {
            var svg = d3.select("body").append("svg")
                .attr("width", window.innerWidth)
                .attr("height", window.innerHeight)
                .attr("class", "svg")
                .call(d3.zoom().on("zoom", function (event) {
                    svg.attr("transform", event.transform)
                }))
                .append("g")
            d3.select("svg").on("dblclick.zoom", null)
            //var linkContainer = svg.append("g").attr("class", "linkContainer")
            var nodeContainer = svg.append("g").attr("class", "nodeContainer")
            var forceLayout = d3.forceSimulation()
                .force("charge", d3.forceManyBody().strength(-25))
                .force("center", d3.forceCenter(window.innerWidth / 2, window.innerHeight / 2))
                .force("collision", d3.forceCollide().radius(50))
            //###############################################
            //################## initialize #################
            //###############################################
            init()
            function init() {
                nodes = nodeContainer.selectAll(".node")
                    .data(graph.nodes, function (d) { return d.id; })
                    .join("g")
                    .attr("class", "node")
                    .attr("id", function (d) { return "node" + d.id; })
                    .call(d3.drag()
                        .on("start", dragStarted)
                        .on("drag", dragged)
                        .on("end", dragEnded)
                    )
                nodes.selectAll("circle")
                    .data(d => [d])
                    .join("circle")
                    .attr("r", 40)
                    .style("fill", "whitesmoke")
                    .on("click", addNode)
                nodes.selectAll("text")
                    .data(d => [d])
                    .join("text")
                    .attr("dominant-baseline", "central")
                    .attr("text-anchor", "middle")
                    .attr("id", function (d) { return "text" + d.id })
                    .attr("pointer-events", "none")
                    .text(function (d) {
                        return d.id + " " + d.type
                    })
                forceLayout
                    .nodes(graph.nodes)
                    .on("tick", tick)
            }
            //add node function
            function addNode(event, d) {
                thisNode = d
                var newNode = {
                    "id": graph.nodes.length + 1,
                    "type": "drinks",
                    x: thisNode.x,
                    y: thisNode.y
                }
                graph.nodes.push(newNode)
                init()
            }
            //tick function
            function tick() {
                nodes.attr("transform", function (d) {
                    return "translate(" + d.x + "," + d.y + ")";
                });
            }
            //drag function
            function dragStarted(event, d) {
                if (!event.active) forceLayout.alphaTarget(0.3).restart();
                d.fx = d.x;
                d.fy = d.y;
            }
            function dragged(event, d) {
                d.fx = event.x;
                d.fy = event.y;
            }
            function dragEnded(event, d) {
                if (!event.active) forceLayout.alphaTarget(0);
                d.fx = undefined;
                d.fy = undefined;
            }
        }
        d3.json(data).then(onLoad).catch(err => console.log(err))
    </script>
</body>
</html>
