dongtun2572
dongtun2572
2015-10-06 07:13

将D3.js与symfony2一起使用

已采纳

I just started learning php for a few weeks and now I'm using Symfony2 as a framework. So, I have very few knowledges using Symfony.

What I'm trying to do now is, I want to implement this D3 tutorial but rather than use plain php, I want to use Symfony.

So, what I did until now :

  1. Created a database called 'homedb' and I fill it exactly as the tutorial did.
  2. Managed to connect symfony with the database (modified in parameters.yml)
  3. Created a new bundle call TreeBundle.
  4. Created a controller called DataController to fetch data from the database.
  5. Created a html.twig file to display the data.

I converted this file : data.php

<?php
    $username = "homedbuser"; 
        $password = "homedbuser";   
        $host = "localhost";
    $database="homedb";

    $server = mysql_connect($host, $username, $password);
    $connection = mysql_select_db($database, $server);

    $myquery = "SELECT  `date`, `close` FROM  `data2`";

    $query = mysql_query($myquery);   
    if ( ! $query ) {
        echo mysql_error();
        die;
    }

    $data = array();

    for ($x = 0; $x < mysql_num_rows($query); $x++) {
        $data[] = mysql_fetch_assoc($query);
    }

    echo json_encode($data);     

    mysql_close($server);

into this file : DataController.php

<?php
// src/Dependency/TreeBundle/Controller/DataController.php
namespace TreeBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

class DataController extends Controller
{
     /**
     * @Route("/tree")
     */

    public function queryAction()
    {
        $em = $this->getDoctrine()->getEntityManager();

        $query=$em->createQuery(
            'SELECT date AND close
            FROM data2'
            );

        $list = $query->getResult();
        return new JsonResponse($list);

    }
    return $list->render('DependencyTreeBundle:Data:simple-graph.html.twig'); 
}

but, I got this error :

Parse Error: syntax error, unexpected 'return' (T_RETURN), expecting function (T_FUNCTION)

I know this is just a tiny error from my erroneous code. Anyone could help me to correctly converted this script?

P/S : For my simple-graph.html.twig, I just use {{source(simple-graph.html)}} to just return the content without rendering it.

UPDATE 1

I just edited my code as follow to fetch the data from database and convert it to json.

public function queryAction()
{
    $em = $this->getDoctrine()->getManager();

    $sql = " 
    SELECT date,
           close
      FROM data2
    ";

    $stmt = $this->getDoctrine()->getManager()->getConnection()->prepare($sql);
    $stmt->execute();
    return $stmt->fetchAll();
    $json = json_encode($stmt);
    return $json-->render('DependencyTreeBundle:query:simple-graph.html.twig');
}

But, I got this error this time : The controller must return a response (Array(0 => Array(date => 1-May-12, close => 58.13), 1 => Array(date => 30-Apr-12, close => 53.98), ,....

Seems like the data is fetched but failed to convert it as json..

UPDATE 2

Here is my new code thanks to @adiii4 for the suggestion. But this code has error : Attempted to load class "TreeBundle" from namespace "Dependency\TreeBundle". Did you forget a "use" statement for another namespace?

<?php
// src/Dependency/TreeBundle/Controller/DataController.php
namespace Dependency\TreeBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

class DataController extends Controller
{
     /**
     * @Route("/tree")
     */

    public function queryAction()
    {
        $em = $this->getDoctrine()->getManager();

        $sql = " 
                SELECT date,
                close
                FROM data2
                ";

        $stmt = $this->getDoctrine()->getManager()->getConnection()- >prepare($sql);

        $stmt->execute();

        $stmt->fetchAll();

        $list = json_encode($stmt);

        return $this->render('DependencyTreeBundle:Data:simple-graph.html.twig', array('data' => $list));
    }

}

UPDATE 3

I think I managed to fetch the data and convert to json correctly. Now, I need to visualized the data by calling D3 in the html file. Is it possible just to embed the html file in Twig and let Twig alone do the rest? Or do I need to convert all of it to Twig syntaxes?

Here is the source code of the simple-graph.html :

        <!DOCTYPE html>
        <meta charset="utf-8">
        <style> /* set the CSS */

        body { font: 12px Arial;}

        path { 
            stroke: steelblue;
            stroke-width: 2;
            fill: none;
        }

        .axis path,
        .axis line {
            fill: none;
            stroke: grey;
            stroke-width: 1;
            shape-rendering: crispEdges;
        }

        </style>
        <body>

        <!-- load the d3.js library -->    
        <script src="http://d3js.org/d3.v3.min.js"></script>

        <script>

        // Set the dimensions of the canvas / graph
        var margin = {top: 30, right: 20, bottom: 30, left: 50},
            width = 600 - margin.left - margin.right,
            height = 270 - margin.top - margin.bottom;

        // Parse the date / time
        var parseDate = d3.time.format("%d-%b-%y").parse;

        // Set the ranges
        var x = d3.time.scale().range([0, width]);
        var y = d3.scale.linear().range([height, 0]);

        // Define the axes
        var xAxis = d3.svg.axis().scale(x)
            .orient("bottom").ticks(5);

        var yAxis = d3.svg.axis().scale(y)
            .orient("left").ticks(5);

        // Define the line
        var valueline = d3.svg.line()
            .x(function(d) { return x(d.date); })
            .y(function(d) { return y(d.close); });

        // Adds the svg canvas
        var svg = d3.select("body")
            .append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
            .append("g")
                .attr("transform", 
                      "translate(" + margin.left + "," + margin.top + ")");

        // Get the data
        d3.json("data.php", function(error, data) {
            data.forEach(function(d) {
                d.date = parseDate(d.date);
                d.close = +d.close;
            });

            // Scale the range of the data
            x.domain(d3.extent(data, function(d) { return d.date; }));
            y.domain([0, d3.max(data, function(d) { return d.close; })]);

            // Add the valueline path.
            svg.append("path")
                .attr("class", "line")
                .attr("d", valueline(data));

            // Add the X Axis
            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(xAxis);

            // Add the Y Axis
            svg.append("g")
                .attr("class", "y axis")
                .call(yAxis);

        });

        </script>
        </body>

What I did just now, in my simple-graph.html.twig is, I just outsource the json data, and call the html file to do the rest. Obviously, I was thrown with this error : Unable to find template "{}" in DependencyTreeBundle:Data:simple-graph.html.twig at line 2

Here is my code in my simple-graph.html.twig :

{# src/Dependency/TreeBundle/Resources/views/simple-graph.html.twig #}
{{ source(data) }}
{{ source('public/html/simple-graph.html') }}

Does anyone have idea? I appreciate it a lot.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • dounaoji2054 dounaoji2054 6年前

    You get your second error because you can't call two return statements in a function! And since a controller function in symfony expects always a Response Object you get this error because this first return statement returns NOT a response object:

    return $stmt->fetchAll();
    

    Your controller function needs to look like this:

    public function queryAction()
    {
        $em = $this->getDoctrine()->getManager();
        $query=$em->createQuery(
            'SELECT date AND close
            FROM data2'
            );
    
        $list = json_encode($query->getResult());
    
        return $this->render('DependencyTreeBundle:query:simple-graph.html.twig', array('data' => $list));
    }
    

    Then you can output your json in your template like this

    {{ source(data) }}
    

    Also did you create an entity class for you database table?

    Update

    Just a little enhancement:

    When you're using raw sql queries without entities fetch your data like this:

        $conn = $this->get('database_connection');
        $list = $conn->fetchAll('SELECT date,close FROM data2');
    

    Reference: http://symfony.com/doc/current/cookbook/doctrine/dbal.html

    点赞 评论 复制链接分享