Creating your beautiful report with charts and tables.
We have learned in previous section how to connect to database, pulling data and piping them through series of processes to get meaningful data. Those data are stored in the data stores of the report ready to be used to create beautiful visualization. In this section, we will learn about the view of report and how to use Widgets in your view.
It is another PHP file containing html/css determined how your report
will appear. Normally, the view file will be put in the same folder with your report class file
and has suffix .view.php
.
/
├── SaleReport.php
└── SaleReport.view.php
Widget is the component of your report view. It takes the data from report's dataStore and
represent them in meaningful way. Widget can be anything, text, tables or charts.
All of them are derived from \koolreport\core\Widget
class.
<?php
use \koolreport\widgets\koolphp\Table;
?>
<h1>Sale Report</h1>
<?php
Table::create(array(
"dataStore"=>$this->dataStore('sales'),
"columns"=>array("product","sale_amount")
));
?>
A report can have many different views. Each view may hold different charts/tales describe the same data or each view is for different purpose. The purpose could be to display html on web or to generate PDF, XML, JSON.
<?php
...
$saleReport = new SaleReport();
$saleReport->run();
$saleReport->render(); //--> This will render the default view SaleReport.view.php
...
$saleReport->render("SaleReport_AnotherView");//--> This will render the view: SaleReport_AnotherView.view.php
Sometime we may need to get the report rendered content to further process.
By enter true
in second parameter of render()
function,
it will return the content instead of sending content to browser.
$content = $saleReport->render("SaleReport",true);//--> Return the view content
Table
widget help us to display data in table format.
It's classname is \koolreport\widgets\koolphp\Table
Let look at below example before we go details on the options.
<?php
use \koolreport\widgets\koolphp\Table;
?>
<h1>Sale Report</h1>
<?php
Table::create(array(
"dataStore"=>$this->dataStore('sales'),
"columns"=>array(
"product"=>array(
"label"=>"Product Name"
),
"sale_amount"=>array(
"type"=>"number",
"label"=>"Sale Amount",
"prefix"=>"$"
)
),
"cssClass"=>array(
"table"=>"table table-bordered"
)
));
?>
Name | type | default | description |
---|---|---|---|
dataSource |
mixed |
Set data source for Widget, dataSource accepts DataStore, DataSource, Process object or even data in array format
|
|
dataStore |
object | Alternative to dataSource |
|
data | array |
* Deprecated, use dataSource instead If you do not want to use dataStore, you may use this properies
to set data on the fly. The data is format of array of associate array.
|
|
columns | array | List of column to be rendered in table. More details. | |
cssClass | array | Contain css class for table, table's row and table's cell. More details | |
removeDuplicate | array | array() | Set the list of columns which duplicated values will be removed.
Eg.removeDuplicate=>array("country","state")
|
"columns"
options simply contain the list of column you want to
show on the table. The simplest form of columns settings is array of columns name for example:
array("id","name","address")
. More advanced, you can add extra meta data for columns like below:
<?php
Table::create(array(
...
"columns"=>array(
"sale_amount"=>array(
"type"=>"number",
"label"=>"Sale Amount",
"prefix"=>"$"
)
),
...
));
?>
Table
has special "{others}" columns.
This mean that beside columns has been specified settings in "columns"
,
other columns will be added and use the settings specified in {others}
.
This is necessary when you want to give common settings for many columns at the same time.
Or in the case that you do not know name of columns but you know the settings for them.
<?php
Table::create(array(
...
"columns"=>array(
"item"=>array(
"type"=>"string",
),
"{others}"=>array(
"type"=>"number",
"prefix"=>"$",
)
),
...
));
?>
One of important feature in Table
is ability to format value dynamically.
Normally, by settings type
for column, the value of column will be formatted automatically.
However, in some case, you may need manual format, you can do so with formatValue
settings.
formatValue
can be a string or a function. For simple format, you may use string:
<?php
Table::create(array(
...
"columns"=>array(
"amount"=>array(
'formatValue'=>'$ @value', // format to $12
),
),
...
));
?>
Or you can specify in function:
<?php
Table::create(array(
...
"columns"=>array(
"amount"=>array(
'formatValue'=>function($value)
{
return "$ ".$value;
}
),
),
...
));
?>
You can specify css for a specific column. The "cssStyle"
can be css string or an array of component "th"
, "td"
, "tf"
<?php
Table::create(array(
...
"columns"=>array(
"amount"=>array(
"cssStyle"=>"text-align:right"
),
"customerName"=>array(
"cssStyle"=>array(
"th"=>"font-weight:bold;text-align:center",
"tr"=>"text-align:center",
"tf"=>"text-align:center",
)
)
),
...
));
?>
You can show or hide the header of table simply by setting "showHeader"=>true
or "showHeader"=>false
Table
has capability to show aggregated result of a column at footer.
To do so you need to turn on footer by setting "showFooter"=>"top"
or "showFooter"=>"bottom"
.
On the column you want to aggregate, you set "footer"=>"sum"
.
The Table support "avg"
, "min"
, "max"
operation as well.
<?php
Table::create(array(
...
"showFooter"=>"bottom",
"columns"=>array(
"amount"=>array(
"footer"=>"sum"
),
"sale"=>array(
"footer"=>"avg",
"footerText"=>"Avg Sale: @value",
)
),
...
));
?>
The "footerText"
can be used to set any text at footer of column, it also can act
as template. In above example, the @value
will be replace with average of sale.
Name | type | default | description |
---|---|---|---|
table | string |
List of class for <table> tag.
If you use Bootstrap, you can set
"table"=>"table table-bordered"
|
|
tr | string, function |
|
|
th | string, function |
|
|
td | string, function |
Example:
|
Table
can be paginated with following settings:
<?php
Table::create(array(
...
"paging"=>array(
"pageSize"=>7,
"pageIndex"=>0,
"align"=>"center"
)
));
?>
The parameter pageSize
sets number of row in a page.
The pageIndex
can be used to set current page for Table, its default value is
0
which indicated table is in the first page.
The align
is used to set position of pager, its value
can be "left"
, "right"
and "center"
.
Table
supports the following client events
Name | description |
---|---|
rowClick |
Triggered when table row is clicked |
<?php
Table::create(array(
...
"clientEvents"=>array(
"rowClick"=>"function(e){
console.log(e.rowIndex);
console.log(e.rowData);
console.log(e.table);
}"
));
?>
Google Charts is a great package providing various types of charts more than enough to visualize your data. What is the best thing? Google Charts is totally free.
According to Google Charts term of service, you need to load chart library from google which means that if you are offline, Google Charts will not load.
Below are common settings for Google Charts.
Name | type | default | description |
---|---|---|---|
dataSource | object |
Set the source of data for widget, accept DataStore, DataSource, Process and even array
|
|
dataStore | object | This is alias name of dataSource |
|
colorScheme | array | Set color scheme for google charts ex. "colorScheme"=>array("#000","#444","#888","#ccc"); |
|
columns | array | The list of columns to export to chart | |
width | string | "400px" | Width of chart |
height | string | "300px" | Height of chart |
options | array | This is the options for specific charts. It may vary from charts to charts so for more information, please look at example for specific chart below and its options. |
Google Charts supports following events:
name | description | params |
---|---|---|
itemSelect |
Trigger when an item on chart is selected for example the bar in BarChart or a pie in PieChart |
|
rowSelect |
Trigger when a row on chart is selected, it is used in GeoChart widget |
|
columnSelect |
Trigger when a column on chart is selected |
|
select |
Trigger on all selection on chart |
|
<?php
ColumnChart::create(array(
...
"clientEvents"=>array(
"itemSelect"=>"function(params){
console.log(params.selectedValue);
}"
)
));
?>
LineChart class name is \koolreport\widgets\google\LineChart
. Please see the example code below
<?php
use \koolreport\widgets\google\LineChart;
?>
<?php
LineChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
BarChart class name is \koolreport\widgets\google\BarChart
. Please see the example code below
<?php
use \koolreport\widgets\google\BarChart;
?>
<?php
BarChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
ColumnChart class name is \koolreport\widgets\google\ColumnChart
. Please see the example code below
<?php
use \koolreport\widgets\google\ColumnChart;
?>
<?php
ColumnChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
PieChart class name is \koolreport\widgets\google\PieChart
. Please see the example code below
<?php
use \koolreport\widgets\google\PieChart;
?>
<?php
PieChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
DonutChart class name is \koolreport\widgets\google\DonutChart
. Please see the example code below
<?php
use \koolreport\widgets\google\DonutChart;
?>
<?php
DonutChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
LineChart class name is \koolreport\widgets\google\ScatterChart
. Please see the example code below
<?php
use \koolreport\widgets\google\ScatterChart;
?>
<?php
ScatterChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
AreaChart class name is \koolreport\widgets\google\AreaChart
. Please see the example code below
<?php
use \koolreport\widgets\google\AreaChart;
?>
<?php
AreaChart::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
Map class name is \koolreport\widgets\google\Map
. Please see the example code below
<?php
use \koolreport\widgets\google\Map;
?>
<?php
Map::create(array(
"dataStore"=>$this->dataStore('sales')
"width"=>"400px",
"height"=>"300px",
"columns"=>array(
"date"=>array(
"label"=>"Date",
"type"=>"datetime"
),
"sale_amount"=>array(
"label"=>"Sale Amount",
"type"=>"number",
"prefix"=>"$"
)
),
"options"=>array(
"title"=>"Sale Performance"
)
));
?>
Other that those common chart above, Google library contains many other charts
such as Histogram, OrgChart, GeoChart etc. All are included in \koolreport\widgets\google
namespace which you can explore further. The common settings are the same but you need to refer
to Google Charts documentation for details of data structure and availale options for each charts.
SubReport
is a feature of KoolReport that allows another report can be loaded inside a main one.
The greatest feature is the ability to update a sub report through AJAX.
The SubReport feature comes from the needs of dividing a big report into smaller reports for better management which we called "divide and conquer" strategy. Also by dividing into smaller and separated reports, we promote the reusable code among reports, for example a subreport can be used in two different report.
Let say we have a ParentReport
and would like to have a ChildReport
inside.
<?php
// ChildReport.php
class ChildReport extends \koolreport\KoolReport
{
function settings()
{
return array(
"dataSources"=>array(
"automaker"=>array(
"connectionString"=>"mysql:host=localhost;dbname=automaker",
"username"=>"root",
"password"=>"",
"charset"=>"utf8"
),
)
)
}
function setup()
{
$this->src("automaker")->query("
SELECT customerNumber,customerName from customers
")->pipe($this->dataStore("customers")))
}
}
<?php
// ChildReport.view.php
use \koolreport\widgets\koolphp\Table;
?>
<?php
Table::create(array(
"dataStore"=>$this->dataStore("customers"),
));
?>
<php
require "ChildReport.php";
class ParentReport extends \koolreport\KoolReport
{
use \koolreport\core\SubReport;
function settings()
{
return array(
"subReports"=>array(
"childreport"=>ChildReport::class
)
)
}
function setup()
{
}
}
<?php
//ParentReport.view.php
?>
<html>
<head>
<title>Parent Report
</head>
<body>
<h1>Parent Report
<div>
<?php $this->subReport("childreport"); ?>
</div>
</body>
</html>
As you expected, the parent report will render with child report inside.
One of greatest feature of sub report is that you may only render the child report through parent report. If you want to render any child report, you do:
<?php
$report = ParentReport(array(
"@subReport"=>"childreport"
));
We are able to partially update the view of child report at client-side from parent report. To do so, in the parent report, you do:
<script type='text/javascript'>
function update()
{
subReport.update("childreport",{
"any_param":"any_value"
});
}
</script>
By calling the update() function the child report will update its view. The parameters inserted at the end will be transferred to child report at server-side, the child report will render updated view and refeshed at client-side.
A widget normally contain a widget class and a widget template. The widget class will take care of the logic layer preparing data to be rendered in widget template.
/
├── my_widget_asset_folder/
│ ├── mywidget.css
│ └── mywidget.js
├── MyWidget.php
└── MyWidget.tpl.php
MyWidget.php
<?php
class MyWidget extends \koolreport\core\Widget
{
protected $anyParam;
protected function onInit()
{
// Get called when the widget is initiated
// You may access the widget settings params through $this->params
$this->anyValue= $this->params["anyValue"];
}
protected function resourceSettings()
{
// You only need this function if your widget requires client resource like js or css
// Or it need library such as jquery, font-awesome
return array(
"library"=>array("jQuery"),//If you require "jquery","font-awesome" or "raphael" or just delete it
"folder"=>"my_widget_asset_folder", // Folder that contains resources for client
"js"=>array("mywidget.js"), //List all required js
"css"=>array("mywidget.css"), // List all required css
)
}
protected function onRender()
{
// Here you got to prepare data to render
// Call $this->template() to render widget template with data.
$this->template("MyWidget",array(
"any_variable"=>$any_variable
));
}
}
MyWidget.tpl.php
<h3>My widget rendering</h3>
<?php
// Your variable input in the $this->template() function will be available as well
echo $any_variable;
//The $this variable refers to the your widget's object.
?>
<script type="text/javascript">
KoolReport.widget.init(<?php echo json_encode($this->getResources()); ?>,function(){
//Any javascript code to initiate your widget if required.
});
</script>