views:

510

answers:

1

I'm planning on adding some flot charts to my site, and i'm wondering are there any recommendations on the best approach for handling this. I have existing model and controller classes that query the DB, and a simple .phtml to render this data as a table.

One approach is to add a new flot.phtml file, and have this class handle the creation of data as required by the flot chart API. The controller would then be updated to pass the queried DB data, to the 'index.phtml' and 'flot.pthml' view files. Its quick and simple, but I'm not sure i'll get much reuse from the logic within the flot.phtml file.

The second option would be to write some class, that would have methods to set the x/y axis, the line types and the add the various datasets. This would basically dump back a content of the 'source' script element, and the final phtml file would just look after the chart size and positioning on the page. Should this component be a controller, should it be a actionhelper? Since it will create source code that will be included in the final html file, are there existing components within Zend that i should extend from or reuse?

Basically, i'm looking for any points that people might want to suggest. If i get something working i'll post it here later?

+1  A: 

I've used jpGraph a fair bit (generates graphs on the server side from php) and have developed some view action helpers that do all the hard work for me. So I call the helpers with a few basic parameters (eg title, width, height) and an array of data (passed in from the controller) and the helper does the rest. It makes a nice clean readable .phtml file, especially when there are multiple graphs per page.

I've not seen any Zend_ components that will do much of this for you.

[updated 12 Nov: added sample code below]

class Zend_View_Helper_RenderAverageDollarSaleGraph
{
    protected $fileName = 'averageDollarSale.jpg';

    //-------------------------------------------------------------------------
    /*! \brief
        \param
        \return
    */
    function renderAverageDollarSaleGraph( $monthSales ) 
    {
        $labels = array( '', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' );
        $startDate = date( 'Ym', mktime( 0, 0, 0, date( 'm' ) - 1, 1, date( 'Y' ) - 2 ));
        $result = $label = $csimLabels = array();
        foreach ($monthSales as $row)
        {
            $date = sprintf( '%d%02d', $row['paid_year'], $row['paid_month'] );
            if ($date < $startDate) continue;
            $label[]= $labels[ $row['paid_month'] ] . "\n" . substr( $row['paid_year'], -2 );
            $monthName = $row['paid_month'] == 1 ? substr( $row['paid_year'], -2 ) : $labels[ $row['paid_month' ] ];
            $result[] = $row['transactions'] <= 0 ? NULL : ($row['total'] / $row['transactions']);
            $csimLabels[]= $labels[ $row['paid_month'] ] . ' $%0.2f';
        }
        $graph = $this->createGraph();
        $graph->SetScale("intint");
        $graph->title->Set( 'Average Dollar Sale' );
        $graph->xgrid->Show( true );
        $graph->ygrid->Show( true );
        $p1 = new LinePlot(array_values( $result ));
        $p1->mark->SetType(MARK_CIRCLE);
        $p1->mark->SetColor( '[email protected]' );
        $p1->SetCSIMTargets( array_fill( 0, count( $csimLabels ), '#' ), $csimLabels );
        $graph->Add($p1);
        $graph->xaxis->SetTickLabels( $label );
        $graph->Stroke( SITE_VAR_PATH . $this->fileName );
    }
}

The above is a cut down version: the full version checks the timestamp on the file and only regenerates if the data is more than a day old.

Steve
hey steve, i'm wondering could you post some code? from your view action helper, since i'd be interested to see you implementation.
emeraldjava
added code as requested. if you need more, let me know
Steve