Thursday, July 2, 2009

Create Dojo grid in Zend Framework- a nice example

About a month or two earlier when I used dojo calendar in my application and write article about the Zend Framework and dojo I was wondering why zend make collaboration with zend. But today when I created a grid using zend dojo I feel the real power of the dojo in Zend framework. In this article I am going to give a simple example and create a grid using Zend framework and dojo.

At the end of this tutorial we will have a grid like the following

So let’s feel the power of dojo in zend.
First execute the following query for creating a table.
CREATE TABLE 'jobs' (
'id' int(11) NOT NULL auto_increment,
'title' varchar(50) NOT NULL,
'description' text,
'posted_date' datetime default NULL,
PRIMARY KEY ('id')
)

This will create a table in your database.

Create a model in your models directory and write the following code in it.
class Jobs extends Zend_Db_Table_Abstract
{
protected $_name='jobs';
public function getJobsData()
{
$select = $this->_db->select()
->from($this->_name);
$results = $this->getAdapter()->fetchAll($select);
return $results;
}
}


and save this table as Jobs.php

In the code above, we first extend our model from Zend_Db_Table_Abstract, define its name and define our custom function getJobsData() that fetch all the rows in the jobs table. We return the results as an array.

Next create a controller JobsController in you controller’s directory and place the following code in it.
<?php
class JobsController extends Zend_Controller_Action
{
public function viewAction()
{
}

public function recordsAction()
{
$jobs = new Jobs();
$data= $jobs->getJobsData();
$dojoData= new Zend_Dojo_Data(’id’,$data,’id’);
echo $dojoData->toJson();
exit;
}
}

In the above code we create two action view and records. We have placed nothing in the view action. In the recordsAction, we create an instance of Jobs model class.and then call its getJobsData() method which will give us an array of records. Next we create an instance of Zend_Dojo_Data() and give the fetched data to it. And finally we echo the data converted it into the Json.

We don’t need to create a view for the records action because we have placed exit it the end of this action which will stop rendering of the view. As we will call this action form our grid view template page so no need to define phtml file for it.

However we will need to create template file for our viewAction. In scripts/views/ directory create view.phtml file and place the following code in it.
Zend_Dojo_View_Helper_Dojo::setUseDeclarative();
$this->dojo()->setLocalPath('http://localhost/Zend/js/dojo/dojo/dojo.js')
->addStyleSheetModule(’dijit.themes.tundra’)
->addStylesheet('http://localhost/Zend/js/dojo/dojox/grid/_grid/tundraGrid.css');
echo $this->dojo();

<script type="text/javascript">
dojo.require("dojox.data.QueryReadStore");
dojo.require("dojox.grid.Grid");
dojo.require("dojo.parser");
</script>
<body class="tundra">
<div dojoType="dojox.data.QueryReadStore" jsId="activeStore", url="records"></div>
<div dojoType="dojox.grid.data.DojoData" jsId="model" rowsPerPage="20″ store="activeStore"></div>
<table id="activePastes" dojoType="dojox.grid.Grid" model="model" style="height:300px; width:700px;">
<thead>
<tr>
<th field="id">Id</th>
<th field="title">Title</th>
<th field="description">Description</th>
<th field="posted_date">Posted</th>
</tr>
</thead>
</table>
</body>


Keep in mind this is the main template file where we are creating our gird.

In the first statement I told zend to use declarative instead of programmatic behavior which is default. Next I set local path and add specific stylesheets. Then in the javascript code I used statement

Dojo.requre(’dojox.data.’) etc

To include specific dojo js modules.

In the body tag I specify a class “tundra”. This is important for the stylesheet I have added.

Next tow div’s and table are the main code for creating grid.

The first div fetch the records from the url specified. This url may be different if you fetch records form the other controller or source. Please specify valid url otherwise you will not get what you want.

The next div act as a bridge between our first div and the table. This div take data from the first div and give it to the table for display purposes.

Keep in mind that all the attributes of the div’s and table are compulsory. Removing any of the attribute may result in unvalid records or empty page. So define everything that I have defined. Once you become able to display your records, you can play with these attributes.

Zend Framework: Storing session data in database

In one of my previous post I wrote how to save session data in the database. The reason behind saving session data in database is that data become more secure and can be easily retrieved later on.
Let’s look how simple and easy it is to save session data in database using Zend_Session_SaveHandler_DbTable in Zend Framework.
1. Creating database table for holding session data
Before writing code you will need to create a table in the database for holding session data. Execute the following query for this purpose.
CREATE TABLE `session` (
`id` char(32),
`modified` int,
`lifetime` int,
`data` text,
PRIMARY KEY (`id`)
);


2.Making necessary configuration in your bootstrap file.
You will only need only few lines of code in your bootstrap file.
After making database configuration in your bootstrap file, write the following code.
$config = array(
'name' => 'session',
'primary' => 'id',
'modifiedColumn' => 'modified',
'dataColumn' => 'data',
'lifetimeColumn' => 'lifetime'
);

Zend_Session::setSaveHandler(new
Zend_Session_SaveHandler_DbTable($config));
Zend_Session::start();

In the $config array we tell the name of the table that will store the session information, primary key of the table, column that will store the session modification timestamp(*nix timestamp), column that will store the session data, and the column that save the information about how long the session will last.

After defining this configuration array we call setSaveHandler() method- static method, of the Zend_Session. This setSaveHandler() method accept Zend_Session_SaveHandler_DbTable object. Zend_Session_SaveHandler_DbTable take configuration array as an argument.

We have now done all the necessary configuration. The only thing we will need to do now is to start our session. Session can be started in the bootstrap file, however it’s not necessary for the session to be started here. You can start it in any controller you needed.

Anywhere in your controller, write
$namespace = new Zend_Session_Namespace();
$namespace->name = "faheem";


and check your session table. The table will not only hold session id, but also the modified timestamp of when session was modified, life time of the session and the session data in special format.
Try it. Its really cool.

PHP: Storing session data in database

Session data by default is stored in /tmp directory on the server in the form of text files. It wouldn’t be a good practice to store session information in the default directory because users can easily get these information. You must either change the directory, or the best practice is to store the information the database. Storing session data in the database not only increase your application security, but also provide you an ability to fetch session related information easily from the database.
PHP provide very easy mechanism and functions for storing session information in the database.
In order to store information in the database you will need to have a table containing fields such sessionId for storing unique session Id, sessionData for storing session data and accessDate that store date when session was last accessed.
Once table is successfully created, saving session requires only two steps.
1. Creating function that interact with and store data in the database.
2. Tell PHP to use the functions defined by using session_set_atuo_save() method.
Now let’s discuss these two steps
1. Creating functions for interacting with database
Before using session_set_auto_save() method, we will need to define six method. These method will then be passed as argument to the session_set_auto_save() method. These six methods are each called on the even taken place. Events are fired when session is started, session is closed, session data is read, session data is written, session data is destroyed, and the six argument/function is used for garbage collection. Garbage collection is used to free resources etc.
Now let’s define and discuss functions for each of these events.
(i) Defining a function which will be called when session is started.
$dbConn = null;

function open_session()
{
global $dbConn;
$dbConn = mysqli_connect('host','username','password','dbname') or die('cannot connect to the database');
}

This method is called each time session is started. The function contains code for connecting to the database only. You can place whatever you wish.
(ii) Defining function called when session is closed
function close_session()
{
global $dbConn;
$dbConn = mysqli_close();
}


(iii) Defining function called when session is read

function read_session($sid)
{
global $dbConn;

$q = sprintf('SELECT data FROM sessions WHERE id="%s"', mysqli_real_escape_string($dbConn, $sid));

$r = mysqli_query($dbConn, $q);
if (mysqli_num_rows($r) == 1) {
list($data) = mysqli_fetch_array($r, MYSQLI_NUM);
return $data;
} else {
return '';
}
}

This function take current sessionId as argument and read the data from the database.
(iv) Defining function called when session data is written
function write_session($sid, $data)
{
global $dbConn;

$q = sprintf('REPLACE INTO sessions (id, data) VALUES ("%s", "%s")',
mysqli_real_escape_string($dbConn, $sid), mysqli_real_escape_string($dbConn,
$data));
$r = mysqli_query($dbConn, $q);
return mysqli_affected_rows($dbConn);
}

This function takes two argument sessions current Id and the data to be written. The code written here inserts session id and data into the database table and return number of affected rows.
(v) Defining function, called when session is destroyed
function destroy_session($sid)
{
global $dbConn;

$q = sprintf('DELETE FROM sessions WHERE id="%s"',
mysqli_real_escape_string($dbConn, $sid));
$r = mysqli_query($dbConn, $q);
$_SESSION = array();
return mysqli_affected_rows($dbConn);
}


This function take single argument sessionId and delete the row based on this id.
(vi) Defining function that is called when resource need to be freed.
function clean_session($expire) 
{
global $dbConn;

$q = sprintf('DELETE FROM sessions WHERE DATE_ADD(last_accessed, INTERVAL %d SECOND) < NOW()',
(int)$expire);
$r = mysqli_query($dbConn, $q);
return mysqli_affected_rows($dbConn);
}

This function is used to delete session data from the database based on the $expire argument it accepts.

Now as we have defined all the required function, its time to call session_set_auto_save() method.

Before starting the session you would need to call session_set_auto_save() method as
<?php

session_set_auto_save('open_session','close_session','read_session','write_session','destroy_session','clean_session');

session_start();

……..

?>

Applying Zend_Form decorators to all elements

After writing two posts on how to setDecorators to different form elements I think it is now time to provide a simple way to set decorators to all form elements at once.
Take a look at the following code.
class SimpleForm extends Zend_Form
{
public function __construct($options = null)
{
parent::__construct($options);
$countryList=array(
'United States',
'United Kindom',
'Pakistan'
);

$firstName = $this->createElement('text', 'firstName');
$firstName ->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]+/'))
->addValidator('stringLength', false, array(6, 20))
->setRequired(true)
-> setLabel('First Name:')
->addFilter('StringToLower');

$lastName = $this->createElement('text', 'lastName');
$lastName ->addValidator('StringLength', false, array(6))
->setRequired(true)
-> setLabel('Last Name:');

$address1 = $this->createElement('text', 'address1');
$address1->setLabel('Address1:')
->addValidator('StringLength', false,array(3,50))
->setValue('')
->setRequired(true);

$address2 = $this->createElement('text', 'address2');
$address2->setLabel('Address2:')
->addValidator('StringLength', false,array(3,50))
->setValue('')
->setRequired(false);

$postalCode = $this->createElement('text', 'postalCode');
$postalCode->setLabel('Postalcode:')
->addValidator('StringLength', false,array(3,15))
->setValue('')
->setRequired(false);

$city = $this->createElement('text', 'city');
$city->setLabel('City:')
->setValue('')
->setRequired(false)
->setAttrib('tabindex','6');

$state = $this->createElement('text', 'state');
$state->setLabel('State:')
->setAttrib('maxlength', 2)
->setValue('')
->setRequired(false)
->setAttrib('tabindex','7');

$country = $this->createElement('select', 'country');
$country->setLabel('Country:')
->setAttrib('class','select')
->addMultiOptions($countryList)
->setRequired(false);

$phone = $this->createElement('text', 'phone');
$phone->setLabel('Phone:')
->setAttrib('maxlength', '25')
->setValue('')
->setRequired(true);

$emailAddress = $this->createElement('text', 'emailAddress');
$emailAddress->setLabel('Email:')
->addValidator('StringLength', false,array(5,50))
->addValidator('EmailAddress')
->setValue('')
->setRequired(true);

$this->addElements( array (
$firstName,
$lastName,
$address1,
$address2,
$postalCode,
$city,
$state,
$country,
$phone
));

$this->setElementDecorators(array(
'viewHelper',
'Errors',
array(array('data'=>'HtmlTag'),array('tag'=>'td')),
array('Label',array('tag'=>'td')),
array(array('row'=>'HtmlTag'),array('tag'=>'tr'))
));

$this->setDecorators(array(
'FormElements',
array(array('data'=>'HtmlTag'),array('tag'=>'table')),
'Form'
));
}
}

If you have read my previous post on decorators, you will easily understand the code. However those how are new to my blog and decorators may need some explanation.
As usual we are extending our form from Zend_Form, define our constructor, call parent constructor and then define our elements.
The most important line are after we add elements to our form. The code
$this->setElementDecorators(array(
'viewHelper',
'Errors',
array(array('data'=>'HtmlTag'),array('tag'=>'td')),
array('Label',array('tag'=>'td')),
array(array('row'=>'HtmlTag'),array('tag'=>'tr'))
));

simply set decorators to all the elements to the form elements. Here we are define that close label in “td”, form elements in “td” and put both these in “tr”.
If you want to set decorators to only few elements then
$this->setElementDecorators(array(
'viewHelper',
'Errors',
array(array('data'=>'HtmlTag'),array('tag'=>'td')),
array('Label',array('tag'=>'td')),
array(array('row'=>'HtmlTag'),array('tag'=>'tr'))

),array('firstname','lastname'));

This code will set decorators to only fistname and lastname element of the form. Rest of the form elements will be render in the default decorators.
At the end we define
$this->setDecorators(array(
'FormElements',
array(array('data'=>'HtmlTag'),array('tag'=>'table')),
'Form'
));

This define the form level decorators. We are putting “table” tag after “form” tag. So all the row will be wrapped in table.

Zend Framework Session usage and examples

Session handling was one of the boring topic in plan php atleast for me, but in Zend Framework it really shines. If you like to work with Object oriented programming, you will definitely become fan of it.
In this article I’m going to discuss some useful techniques of using Zend Framework Session and Session namespace.
Keep in mind that Both Zend_Session and Zend_Session_Namespace extends abstract class Zend_Session_Abstract. So both inherit methods avaliable in Zend_Session_Abstract automatically.
If you want to go under the hood, you can open Zend/Session/Abstract.php and have a look at the functions available.
Instead of delve into the function available, I’d rather discuss some useful techniques.
Although you can create Zend_Session class object, however I would recommend Zend_Session_Namespace object instead. You can instantiate session as
$sess = new Zend_Session_Namespace(’MyNamespace’);

Here the argument is optional, however it is better to pass it. If don’t pass, Zend Session Namespace will assign its name a string “default”.
To store values, you will need to do the following.
$sess->username = ‘you_name’;

Later in your code, you will need to do the following to retrieve value from the session.
    $session = new Zend_Session_Namespace(’MyNamespace’);

$userName = $sess->username;

This was a simple example of how to assign values to session and later retrieve. Now I’m going to discuss some of its important method.
To check whether or not session exist, write the following.
    If (Zend_Session::sessionExist()) {

// do something.

}

sessionExist() is static method available in Zend_Session.

Another very important method is rememberMe() available in Zend_Session. This is used to make your session persistent.
Its syntax is
Zend_Session::rememberMe(60*60*24*7);

The number passed as an argument specify for how long the session will be available. What I have done means that session will be there for a week.
To destroy this you will need to call the following function on the logout of your application.
Zend_Session::forgetMe();

Another method
destroy(bool,bool), take two Boolean arguments. This destroy the entire persistent data. Keep in mind that Zend_Session_Namespace data will not be destroyed. You can retrieve that data even after you call
Zend_Session::destroy(false);

To completely logout you will need to do the following
Zend_Session::destroy(true);

We now passed true instead of false.
The above methods were anyhow related to Zend_Session class. To check the individual namespaces you can use the following function
Zend_Session::namespaceIsset(’MyNamespace’);

This will check whether the specified namespace has been set.
To unset the particular namespace, you will need to write the following.
Zend_Session:: namespaceUnset(’MyNamespace’);

There are plenty of other options available. But I don’t thing you will mostly need those.

If you do need extra functionality, don’t hesitate to open Zend_Session_Abstract.php, Zend_Session_Nampspace.php, and Zend_Session.php.
If you still finding it difficult to understand, do post your comments. I’d be glad to give you solution to your problem.

Wednesday, July 1, 2009

Creating JQuery form in Zend Framework

While few months back, I wrote an article on how to make Dojo Form in Zend Framework. Although dojo has numerous features, however most of the developers around prefer JQuery and prototype.
When Zend provide JQuery extension I wrote and article on how to use JQuery date picker.
While most of guys visited that article demand writing an article on how to create JQuery form in Zend Framework.
So I’m here to show you how to use JQuery extension provide with latest version of Zend Framework for creating wonderful JQuery form.
You will need to follow the steps bellow to create JQuery form.
1. Placing ZendX directory in right place
2. Make necessary configuration in bootstrap file
3. Write necessary code in your layout.phtml file.
4. Create JQuery form
5. and show that form in the template.

Placing ZendX directory in right place:
When you download latest version of Zend Framework and extract the zip file. You will see a directory called “extras”. When open that directory you will find ZendX folder. Copy this to your
Library/ folder at the same level of your Zend directory
You directory structure will be like this.
Library/
Zend/
ZendX/

Making necessary configuration in bootstrap:
After placing the directory you will need to add a bit of code in your bootstrap file.
Add the following lines to your bootstrap file.
$view = new Zend_View();
$view->addHelperPath("ZendX/JQuery/View/Helper", "ZendX_JQuery_View_Helper");
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRenderer->setView($view);
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

In the code above, we instantiate our Zend_View object, set helper path, add view to the viewRenderer and finally add viewRenderer the helper broker.
Keep in mind that if you have already instantiate Zend view in your bootstrap, you don’t need to instantiate it twice.
Write necessary code in your layout.phtml file:
The only line you will need to include in your layout file is
echo $this->jQuery();

If you don’t use two step view, you can include this line at the top of each of your view template file instead.
Create JQuery form:
Now you have done all the necessary configuration, its time to create the actual form.
Create JQuery form in Zend framework is piece of cake.
If you want to create form in your controller, write the following code.
$form = new ZendX_JQuery_Form();
$date1 = new ZendX_JQuery_Form_Element_DatePicker(
'date1',
array('label' => 'Date:')
);
$form->addElement($date1);
$elem = new ZendX_JQuery_Form_Element_Spinner(
"spinner1",
array('label' => 'Spinner:')
);
$elem->setJQueryParams(array(
'min' => 0,
'max' => 1000,
'start' => 100)
);
$form->addElement($elem);
$this->view->form = $form;

In the code above we have created our JQuery form object, and add two element date and spinner to it. And then assigned the form to the view template file. Although you can create the form in your controller, however I will strongly discourage it. I will prefer using separate php file and add following code to that file.
class JQueryForm extends ZendX_JQuery_Form
{
public function init()
{
$this->setMethod('post');
$this->setName('frm');
$this->setAction('path/to/action');

$date1 = new ZendX_JQuery_Form_Element_DatePicker(
'date1',
array('label' => 'Date:')
);

$this->addElement($date1);

$elem = new ZendX_JQuery_Form_Element_Spinner(
"spinner1",
array('label' => 'Spinner:')
);

$elem->setJQueryParams(array('min' => 0, 'max' => 1000, 'start' => 100));
$this->addElement($elem);
}
}

We have extended our form from ZendX_JQuery_Form, set its method, name and action and add two elements date and spinner.
Now in your controller/action
    $form = new JQueryForm();

$this->view->form = $form;

Showing form in the template:
In your view template file add only the following line.
    <?php

echo $this->form;

?>

Zend Framework and dojo checkbox example

Few weeks back, I used dojo check box in my Zend framework application. Scenario was a bit different at that time. I was submitting Zend dojo form on the click event of the checkbox. When I created a form and submitted that onclik, It didn’t give me desired results.
I set its checked value to 1 and unchecked value to 0, however when I submited it always gave me a single value. I was looking for 0 and 1, but it always gave me 0. I thought that It was because I was not using proper submit button for the posting of form.
However when today I used checkbox in normal zend dojo form, it gave me the same result. Oh God, how to fix it.
However as I have played with dojo js files, so I got the solution.
Let’s tell you the trick.
First of all create check box as
$checkbox= $form->createElement(
'checkBox',
'checkbox',
array(
'label' => 'Tricky check box',
'checkedValue' => 1,
'uncheckedValue' => 0
)
);

Now add onclick event to this checkbox element as
$checkbox->setAttrib('onclick','changeValue()');

Now in your view, where you display this form, write the following javascript function
<script>
function changeValue()
{
if(dijit.byId('checkbox').checked){
dijit.byId('checkbox').setValue('1');
} else {
dijit.byId('checkbox').setValue('0');
dijit.byId('checkbox').checked=false;
}

}
</script>

The above code isn’t simple?

Hmm. First we see if we have checked the checkbox, if yes we assign value 1 to it, if not we assign it value 0 and set its checked status to false. This will uncheck the checkbox.

That’s it. Submit your form and you will get desired results.

Doesn’t it help you. Do you have smarter solution than this.

Tell me……