Developers/Getting Started/Getting started with ExtJS and Zend Framework

From Tine 2.0 - Wiki

< Developers‎ | Getting Started

Preface

To help you getting started with ExtJS and Zend we created some simple examples. All examples presume that you have installed the Zend Framework and ExtJS 2.0 on your PHP and MySQL enabled Server. The directory structure should be as follows:

/htdocs/
       /Zend
       /extjs
       /index.php
       /data.php
       /mediadb.js

All the example files will be available at the end of each part.

Part 1 - the basics

Our first example will retrieve the needed data from a pre-defined array, to make your start as easy as possible. The array will get JSON Encoded and returned. It also includes the Zend Loader class to register autoload which helps us to reference Zend classes without the need to include them before.

As we want to add some more functions in the following examples, we need to evaluate which function is beeing called. Including one switch statement, we achieve the following script (called "data.php"):

<?php
    require_once 'Zend/Loader.php';   
    Zend_Loader::registerAutoload();
  
    function getData() { 
    
        $rows = array('0' => array('id' => '1', 'name' => 'Walden', 'author' => 'H.D. Thoreau', 'descr' => '"Walden" is the classic account of two years spent by Henry David Thoreau living at Walden Pond near Concord, Massachusetts.', 'type' => 'book'),
                     '1' => array('id' => '2', 'name' => 'Barry Lyndon', 'author' => 'Stanley Kubrick', 'descr' => 'Thackerays tale of a roguishly charming 18th century Englishman, card shark and con-man whose good fortune and luck finally run out.', 'type' => 'dvd'),
                     '2' => array('id' => '3', 'name' => 'White Blood Cells', 'author' => 'The White Stripes', 'descr' => 'The much anticipated third album by Detroits critically acclaimed brother and sister duo.', 'type' => 'cd'));
   
       $json = Zend_Json::encode($rows);
       echo $json;
   }
      
   switch ($_POST['method']) {
   case 'get':
       getData();
       break;
   }
?>

Initialising extJS

To include all needed files for the extJS Framework to work properly, we create one php file called "index.php". There we define the needed HTML skeleton and load the needed js files (note that our first extJS is also already included here, it's called "mediadb.js"). The source code will be as follows:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>

<head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>eGroupware 2.0 - Example - getting started</title>
   <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
   <link rel="stylesheet" type="text/css" href="extjs/resources/css/xtheme-gray.css" />

   <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
   <script type="text/javascript" src="extjs/ext-all-debug.js"></script>

   <script type="text/javascript" language="javascript" src="mediadb.js"></script>

</head>
<body>
   <\div id="placeholder"><\div>   // please remove the first backslash which was needed for wiki-viewability only
</body>
</html>

You're first extJS Script

After solving all preparations it is now time to take a look at our first extJS code (the file will be named "mediadb.js"). To collect your data and render it to the sortable and resizable table view (called gridpanel in extjs) you just need to follow three steps:

  • define your JsonStore which collects the needed data from your db and loads it
    var media_store = new Ext.data.JsonStore({
       url: 'data.php',
       baseParams: {
           method:   'get'
       },
       id: 'id',
       fields: [
           {name: 'id'},
           {name: 'name'},
           {name: 'author'},
           {name: 'descr'},
           {name: 'type'}
       ],
       remoteSort: false
   });
   // set the default sorting for the corresponding sql query
   media_store.setDefaultSort('name', 'asc');

   // loading the actual data from data.php
   media_store.load();
   // defining the layout (columnmodel) of the table (grid) we want to create
   var mediaGrid_cm = new Ext.grid.ColumnModel([
           {id:'id', header: 'id', dataIndex: 'id', hidden: true },
       	{id:'name', header: 'Name', dataIndex: 'name', width: 200, sortable: true },
           {id:'author', header: 'Author', dataIndex: 'author', width: 150, sortable: true },
           {id:'description', header: 'Description', dataIndex: 'descr', width: 250, sortable: true },
           {id:'type', header: 'Type', dataIndex: 'type', width: 70, sortable: true }
        ]);
   mediaGrid_cm.defaultSortable = true; 


   // defining the grid
   var media_grid = new Ext.grid.GridPanel({
           id: 'Example_mediagrid',
           store: media_store,
           cm: mediaGrid_cm,
           viewConfig: {
               forceFit: true
           },
           sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
           stripeRows: true,
           autoExpandColumn: 'name',
           width:770,
           height:300,
           frame:false,
           iconCls:'icon-grid'
   });
  • attach the gridpanel to the pre-defined DIV element of your "index.php"
   media_grid.render('placeholder');

Thats all to achieve the resulting view:

Example 1.png

Files

To execute this example just download all needed files and put them in the correct directory of your webserver.


Part 2 - changing the data source

Getting Data from an actual database is the next step evolving our first example. First of all we will feed your MySQL DB with the needed tables and data, second we will connect to the DB and get actual data from there.

DB Structure

To create the Data just execute the following MySQL Dump:

CREATE TABLE `egw2_mediadb` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(100) NOT NULL default ,
  `author` varchar(100) NOT NULL default ,
  `descr` text NOT NULL,
  `type` varchar(50) NOT NULL default ,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

INSERT INTO `egw2_mediadb` VALUES (1, 'Walden', 'H.D. Thoreau', '"Walden" is the classic account of two years spent by Henry David Thoreau living at Walden Pond near Concord, Massachusetts.', 'book');
INSERT INTO `egw2_mediadb` VALUES (2, 'Barry Lyndon', 'Stanley Kubrick', 'Thackerays tale of a roguishly charming 18th century Englishman, card shark and con-man whose good fortune and luck finally run out.', 'dvd');
INSERT INTO `egw2_mediadb` VALUES (3, 'White Blood Cells', 'The White Stripes', 'The much anticipated third album by Detroits critically acclaimed brother and sister duo.', 'cd');

Getting Data using Zend DB

To get hold of our just inserted data, we modify our PHP script "data.php". In the following step we utilize Zend DB to establish the connection to our database. In combination with the Zend Registry, we will have access to the just created db object at any time.

$db = Zend_Db::factory('Pdo_Mysql', array(
    'host'     => 'YOUR HOSTNAME',
    'username' => 'YOUR USERNAME',
    'password' => 'YOUR PASSWORD',
    'dbname'   => 'YOUR DBNAME'
));
Zend_Db_Table_Abstract::setDefaultAdapter($db);
Zend_Registry::set('dbAdapter', $db);

To create the SQL request we use the Zend DB Table Class which provides simple access to our Database. To do so we will have to extend the existing abstract class. If the name of the class corresponds with the table name, there's nothing more to do.

class egw2_mediadb extends Zend_Db_Table_Abstract
{
    
}

The returning object will get converted to array and JSON encoded ( Zend JSON).

function getData($sort, $dir) { 
     $db = Zend_Registry::get('dbAdapter');
           
     $table = new egw2_mediadb();
     $rows = $table->fetchAll(NULL, $sort . ' ' . $dir);     
    
     $json = Zend_Json::encode($rows->toArray());
     echo $json;
}

Here's the complete rewritten script:

Ext.onReady(function(){
   
   // defining the data store
   var media_store = new Ext.data.JsonStore({
       url: 'data.php',
       baseParams: {
           method:   'get'
       },
       id: 'id',
       fields: [
           {name: 'id'},
           {name: 'name'},
           {name: 'author'},
           {name: 'descr'},
           {name: 'type'}
       ],
       remoteSort: true
   });
   
   // set the default sorting for the corresponding sql query
   media_store.setDefaultSort('name', 'asc');

   // loading the actual data from data.php
   media_store.load();



   // defining the layout (columnmodel) of the table (grid) we want to create
   var mediaGrid_cm = new Ext.grid.ColumnModel([
           {id:'id', header: 'id', dataIndex: 'id', hidden: true },
       	{id:'name', header: 'Name', dataIndex: 'name', width: 200, sortable: true },
           {id:'author', header: 'Author', dataIndex: 'author', width: 150, sortable: true },
           {id:'description', header: 'Description', dataIndex: 'descr', width: 250, sortable: true },
           {id:'type', header: 'Type', dataIndex: 'type', width: 70, sortable: true }
        ]);
   mediaGrid_cm.defaultSortable = true; 


   // defining the grid
   var media_grid = new Ext.grid.GridPanel({
           id: 'Example_mediagrid',
           store: media_store,
           cm: mediaGrid_cm,
           viewConfig: {
               forceFit: true
           },
           sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
           stripeRows: true,
           autoExpandColumn: 'name',
           width:770,
           height:300,
           frame:false,
           iconCls:'icon-grid'
   });

   // rendering the grid at the defined div-element
   media_grid.render('placeholder');
});

Files

Again here are all the files you need, for download.


Part 3 - Paging

In our third example we want to achieve paging through our result set. To do so we need to touch our datasource "db.php" and our ExtJS File "mediadb.js".

change parameters of getting data

To get only the amount of results we want to show at one time we will have to pass appropriate parameters to the db. We will add the parameters "limit" and "start". Another point is to split our data in the actual results and the number of total entries. This total number is needed to tell the ExtJs how many entries are to be expected. We place a second query for it. Changes will be as follows:

 function getData($sort, $dir, $start, $limit) { 
        $db = Zend_Registry::get('dbAdapter');
            
        $table = new egw2_mediadb();
        $rows = $table->fetchAll(NULL, $sort . ' ' . $dir, $limit, $start);     
        $numRows = $table->fetchAll(NULL);     
        
       
        $data['results'] = $rows->toArray();
        $data['totalcount'] = count($numRows->toArray());
        
        $json = Zend_Json::encode($data);
        echo $json;
    }
      
    switch ($_POST['method']) {
    case get:
        getData($_POST['sort'], $_POST['dir'], $_POST['start'], $_POST['limit']);
        break;
    }

add extjs feature

Our ExtJs Code has to be modified with the following steps. First of all we will need to include the parameter "root" and "totalProperty" in our JsonStore definition. This is to tell the store were the actual data as well as the amout of total entrie is to be found in the incoming json array.

 var media_store = new Ext.data.JsonStore({
       url: 'data.php',
       root: 'results',
       baseParams: {
           method:   'get'
       },
       totalProperty: 'totalcount',
       id: 'id',
       fields: [
           {name: 'id'},
           {name: 'name'},
           {name: 'author'},
           {name: 'descr'},
           {name: 'type'}
       ],
       remoteSort: true
   });

The next step is to define our paging toolbar which will do all the things needed to provide paging functionality.

    // defining the paging Toolbar
    var pagingToolbar = new Ext.PagingToolbar({ // inline paging toolbar
        pageSize: 2,
        store: media_store,
        displayInfo: true,
        displayMsg: 'Displaying entries {0} - {1} of {2}',
        emptyMsg: "No entries to display"
    });     

To include the paging toolbar in our grid we just have to add one line in the grid definition:

[...]
   tbar: pagingToolbar,
[...]

Instead of loading the complete store via

 media_store.load();

we will now load only the displayed parts:

  media_store.load({params:{start:0, limit:2}});

(as we have only 3 example entries we will limit the result to 2)

Thats all you need to achieve paging!

Files

From the current example on, we will only provide the changed files, so you won't have to replace all files. Download them here.

Part 4 - Resizing

Ever wondered how you can easily resize all your content depending on your browser size? We will get there in just two steps.

To do so we will again have to touch "mediadb.js". We include the extjs "viewport" which resizes any element in it to the actual browser size.

var viewport = new Ext.Viewport({
       layout: 'border',
       items: [{
           region: 'center',
           id: 'center-panel',
           useShim:true,
           layout: 'fit',
           split: false,
           border:false,
           items: [ media_grid ]
       }]
 }); 

As you see we include our "media_grid" directly in the viewport. Therefore we wont need our "div" element any more and can remove it from the "index.php".

And thats it!

Files

Again only changed files for download.