Login   Register  
PHP Classes
elePHPant
Icontem

File: demos/060.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Tom Schaefer  >  d3  >  demos/060.php  >  Download  
File: demos/060.php
Role: Example script
Content type: text/plain
Description: shows how to push a sql query result into a grouped bar chart
Class: d3
Output charts using D3.js JavaScript library
Author: By
Last change:
Date: 2012-12-24 05:07
Size: 10,956 bytes
 

Contents

Class file image Download
<?php 

include_once '../d3.classes.inc.php';

class d3GroupedBarChartData {
	protected $username = "root";
	protected $password = "";
	protected $database = "northwind";
	protected $host = "localhost";
	protected $query = "SELECT  IFNULL(country, 'other') AS country, IFNULL(jahr,'Total') as `year`, SUM(profit) as amount FROM sales GROUP BY country, year;";

	public $results = array();
	
	public function __construct($query=null, $conn=null){
		if($query) $this->query = $query;			
		if(is_array($conn)){
			foreach($conn as $key => $val){
				if(property_exists($this, $key)){
					$this->{$key} = $val;
				}
			}
		}
	}
	
	protected function fetchData(){
		$link=mysql_connect($this->host,$this->username,$this->password);
		@mysql_select_db($this->database) or die( "Unable to select database");
		$rs = mysql_query($this->query,$link) or die('Error: '.$this->query);
		if(mysql_num_rows($rs)) {
			$value = null;
			$index = 0;
			while($value = mysql_fetch_assoc($rs)) {
				$this->results[$value["country"]][($value["year"]==""?"other":$value["year"])] = $value["amount"];
				$this->results[$value["country"]]["country"] = $value["country"];
				$index++;
			}
		}
		mysql_close();		
	}
	
	public function getBarValueName(){
		return "amount";
	}
	
	public function getBarTitleName(){
		return "country";
	}
	public function getResults(){
		$results = array();
		foreach($this->results as $row){
			$results[] = $row;
		}
		return $results;
	}
	
	public function execute(){
		$this->fetchData();
	}
	
}

class d3GroupedBarChart {
	/**
	 * @var d3GroupedBarChartData $data
	 */
	protected $data;
	protected $config = array();
	protected $stack = array();
	protected $register = array();
	
	protected $barTitleName;
	protected $barValueName;
	
	public function __construct(d3GroupedBarChartData $data, $config = array()){
		$this->data = $data;
		$this->prepareConfig($config);
	}
	
	protected function has($name){
		return array_key_exists($name, $this->register);
	}
	
	protected function get($name){
		return $this->register[$name];
	}
	
	protected function set($name, $value){
		$this->register[$name] = $value;
		return $this;
	}
	
	protected function add($value){
		$this->stack[] = $value;
		return $this;
	}
	
	protected function prepareConfig($config){
		$this->config = array(
			"width" => 960, "height" => 500, 
			"margin" => array("top" => 20, "right" => 20, "bottom" => 30, "left" => 40),
			"color" => array("#ff0000", "#00ff00", "#0000ff", "#ffff00"),
			
		);		
		$this->config = array_merge_recursive($this->config, $config);
	}
	
	protected function prepareDataSet(){
		$this->data->execute();
		$this->barTitleName = $this->data->getBarTitleName();
		$this->barValueName = $this->data->getBarValueName();
		$this->set("dataset", d3::variable(d3::unescape( json_encode($this->data->getResults()) ),"data"));
		$this->add( $this->get("dataset") );
	}
	
	protected function prepareDimensions(){
		$this->set("margin", d3::variables(array("margin" => o3($this->config["margin"]))) );
		$this->add( $this->get("margin") );
		
		$this->set("width", d3::variable(d3::unescape( $this->config["width"]."-margin.left-margin.right"), "width") );
		$this->set("height", d3::variable(d3::unescape( $this->config["height"]."-margin.top-margin.bottom"), "height") );
		$this->add( $this->get("width") );
		$this->add( $this->get("height") );
	}
	
	protected function prepareOrdinalScale(){
		$this->set("x0", d3()
				->scale(d3::property)
				->ordinal()->rangeRoundBands(array(0, $this->get("width")->getVar()), 0.1)->returnVar("x0")
		);
		$this->add( $this->get("x0") );
		$this->set("x1", d3()
				->scale(d3::property)
				->ordinal()->returnVar("x1")
		);
		$this->add( $this->get("x1") );
	
		$this->set("y", d3()
				->scale(d3::property)
				->linear()->range(array($this->get("height")->getVar(), 0))->returnVar("y")
		);
		$this->add( $this->get("y") );
	}
	protected function prepareColorSet(){
		$this->set("color", d3()
				->scale(d3::property)
				->ordinal()->range($this->getColors())
				->returnVar("color")
		);
		$this->add( $this->get("color") );
	}
	
	protected function getColors(){
		foreach($this->config["color"] as $index => $color){
			$this->config["color"][$index] = d3::escape($color);
		}
		return $this->config["color"];
	}
	
	protected function prepareAxis(){

		$this->set("xAxis", d3()->svg(d3::property)->axis()
				->scale($this->get("x0")->getVar())->orient("bottom")->returnVar("xAxis")
		);
		$this->add( $this->get("xAxis") );
		
		$this->set("yAxis", d3()->svg(d3::property)->axis()
				->scale($this->get("y")->getVar())
				->orient("left")->tickFormat(d3()->format(".2s"))->returnVar("yAxis")
		);
		$this->add( $this->get("yAxis")->linebreak() );
		
	}
	
	protected function prepareCanvas(){
		$this->set("svg", d3()
			->select("body")->append("svg")->linebreak()->tab()
				->attr("width", d3::unescape( $this->get("width")->getVar()."+margin.left+margin.right"))->linebreak()->tab()
				->attr("height", d3::unescape( $this->get("height")->getVar()."+margin.top+margin.bottom"))->linebreak()->tab()
			->append("g")->attr("transform" , d3::unescape('"translate("+margin.left+ "," + margin.top + ")"'))->returnVar("svg")
		);
		$this->add( $this->get("svg")->linebreak() );
		
	}
	
	protected function prepareChart(){
		$this->prepareChartMethods();
		$this->prepareChartBarAxes();
		$this->prepareChartBarColumn();		
		$this->prepareChartLegend();		
	}
	
	protected function prepareChartMethods(){
		
		$this->set("amountNames", d3()->keys(d3::unescape("data[1]"))->filter(function($key){return $key !== "country";})->createVar("amountNames"));
		$this->add( $this->get("amountNames"));

		$this->add( 
			$this->get("dataset")->get()->forEach(d3::unescape("function(d) {d.amounts = amountNames.map(function(name) { return {name: name, value: parseInt((!+d[name]?0:+d[name]))}; });}"))
				->colon()
		);
		
		$this->add(
			$this->get("x0")->get()->domain($this->get("dataset")->get()->map(function($d){return $d->country;}))->colon()
		);
		
		$this->add(
			$this->get("x1")->get()->domain($this->get("amountNames")->getVar())->rangeRoundBands(array(0, $this->get("x0")->get()->rangeBand()))->colon()
		);
		
		
		$this->add(
			$this->get("y")->get()->domain(
				array(
					0, 
					d3::unescape("d3.max(data,function(d){return d3.max(d.amounts,function(d){return d.value;});})")
				)
			)->colon()->linebreak()
		);
	}
	
	protected function prepareChartBarAxes(){

		$this->add( 
			$this->get("svg")->get()
				->append("g")->linebreak()->tab()
				->attr("class", "x axis")->linebreak()->tab()
				->attr("transform", d3::unescape('"transform(0, "+height+")"'))->linebreak()->tab()
				->call($this->get("xAxis")->getVar())
			->colon()
		);
	
		$this->add( 
			$this->get("svg")->get()
				->append("g")->linebreak()->tab()
				->call($this->get("yAxis")->getVar())->linebreak()->tab()
				->append("text")->linebreak()->tab()
				->attr("transform", "rotate(-90)")->linebreak()->tab()
				->attr("y", 6)->linebreak()->tab()
				->attr("dy", ".71em")->linebreak()->tab()
				->style("text-anchor","end")->linebreak()->tab()
				->text($this->barValueName)
			->colon()->linebreak()
		);
		
	}
	
	protected function prepareChartBarColumn(){
		
		$this->set($this->barTitleName, 
			$this->get("svg")->get()
				->selectAll(".".$this->barTitleName)->linebreak()->tab()
				->data($this->get("dataset")->getVar())->linebreak()->tab()
				->enter()->append("g")->linebreak()->tab()
				->attr("class","g")->linebreak()->tab()
				->attr("transform", function($d){return "translate(".$x0($d->country).",0)";})
			->createVar($this->barTitleName)
		);
		
		$this->add( $this->get($this->barTitleName));
		
		$this->add( 
			$this->get($this->barTitleName)->get()
				->selectAll("rect")->linebreak()->tab()
				->data(function($d){return $d->amounts;})->linebreak()->tab()
				->enter()->append("rect")->linebreak()->tab()
				->attr("width", $this->get("x1")->get()->rangeBand())->linebreak()->tab()
				->attr("height", function($d){return $height-$y($d->value);})->linebreak()->tab()
				->attr("x", function($d){return $x1($d->name);})->linebreak()->tab()
				->attr("y", function($d){return $y($d->value);})->linebreak()->tab()
				->style("fill", function($d){return $color($d->name);})->linebreak()
		);
		
	}
	
	protected function prepareChartLegend(){

		$this->set("legend", $this->get("svg")->get()
			->selectAll(".legend")->linebreak()->tab()
			->data($this->get("amountNames")->get()->slice()->reverse())->linebreak()->tab()
			->enter()->append("g")->linebreak()->tab()
			->attr("class", "legend")->linebreak()->tab()
			->attr("transform", function($d, $i){return "translate(0," . $i * 20 . ")";})
			->createVar("legend")
		);
		
		$this->add( $this->get("legend"));
		
		$this->add(
			$this->get("legend")->get()->append("rect")->linebreak()->tab()
				->attr("y", d3::unescape($this->get("height")->getVar()."/2"))->linebreak()->tab()
				->attr("x", d3::unescape($this->get("width")->getVar()."-28"))->linebreak()->tab()
				->attr("width", 18)->linebreak()->tab()
				->attr("height", 18)->linebreak()->tab()
				->attr("fill", $this->get("color")->getVar())
				->colon()
		);
		
		$this->add(
			$this->get("legend")->get()->append("text")->linebreak()->tab()
				->attr("x", d3::unescape($this->get("width")->getVar()."-30"))->linebreak()->tab()
				->attr("y", d3::unescape($this->get("height")->getVar()."/2 +9"))->linebreak()->tab()
				->attr("dy", ".35em")->linebreak()->tab()
				->style("text-anchor", "end")->linebreak()->tab()
				->text(function($d){return $d;})
				->colon()
		);
				
	}
	
	protected function init(){
		$this->prepareDataSet();
		$this->prepareDimensions();
		$this->prepareOrdinalScale();
		$this->prepareColorSet();
		$this->prepareAxis();
		$this->prepareCanvas();
		$this->prepareChart();

		$this->stack[] = "\n";		
		$this->object = implode("\n", $this->stack);		
	}
	
	public function render() {
		$this->init();
		$this->stack[] = "\n";
		return $this->object;
	}
}

?><!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
  fill: steelblue;
}

.x.axis path {
  display: none;
}

</style>             
<script src="http://d3js.org/d3.v3.min.js"></script>
    </head>
    <body>
        <div id="viz"></div>
        <script type="text/javascript">
          <?php 
          $script = new d3GroupedBarChart(new d3GroupedBarChartData());
          echo $script->render();
          ?>        
        </script>
    </body>
</html>