Wednesday, July 1, 2009

Zend Framework Form(Zend_Form) tutorial

I got “The Zahir”, a novel by Paula Coelho about a month back, very sweat one and highly intrigued. It was highly entertaining and most importantly author shared his experiences in a nice way. I learned plenty of new ideas.
Eh, you may think that I am insane, supposed to write about Zend Framework, but discussing a novel.
Well, novel can not only be a good companion of yours, but it also put shade of light on simple things from many angles. This make you think dynamically.
If you are solving a puzzle or implementing your logic, do not think straight forward, give multiple tries and chose a more appropriate solution. Solving a problem will not be hard. You should chose a solution that require less code, small maintenance overhead and most importantly one that will be less resource intensive.
Now lets stick to the topic and discuss how you can use Zend_Form component for creating html form easily, handling filters and errors messages and how to see how easily you can fetch data from the data source and present that in html form and let the visitors change/modify the existing data and save changes to the data source.
I am gona break this topic in three steps.
1. Creating Zend_Form
Although I’ve already discussed creation of Zend_Form in some of my articles but it will be better to discuss it here again.
Creating Zend form is simple is this.
class CustomForm extend Zend_Form
{
public function init()
{

}
}

defined a class by extending it from Zend_Form. This allow access to many of methods already defined in Zend_Form.
The only thing you need to do is to override init() method and create your own element such as input box, select statement, checkboxes, radio buttons and so on.
Defining your own elements don’t take much code. Have a look at the following code.
class CustomForm extend Zend_Form
{
public function init()
{
$this->setMethod('post');
$this->setAction('process/form');

$username = $this->createElement('text','username');
$username->setLabel('Username:')
->setAttrib('size',50);

$this->addElement($username);
}
}

In the code above we have overridden init() method of Zend_Form, set the form request method and action and then defined input element called username. You can put as many elements in this form as you wish. The last statement is used to add element to the forms. To add several elements to the form at once, use addElements() passing array of elements as an argument. You will look an example in the next example.

My entire form look likes
class CustomForm extends Zend_Form
{
public function init()
{
$this->setMethod('post');

$id = $this->createElement('hidden','id');
$firstname = $this->createElement('text','firstname');
$firstname->setLabel('First Name:')
->setAttrib('size',50);
$lastname = $this->createElement('text','lastname');
$lastname->setLabel('Last Name:')
->setAttrib('size',50);
$username = $this->createElement('text','username');
$username->setLabel('Username:')
->setAttrib('size',50);
$email = $this->createElement('text','email');
$email->setLabel('Email:')
->setAttrib('size',50);
$password = $this->createElement('password','password');
$password->setLabel('Password:')
->setAttrib('size',50);

$password2 = $this->createElement('password','password2');
$password2->setLabel('Confirm Password::')
->setAttrib('size',50);
$register = $this->createElement('submit','register');
$register->setLabel("Register")
->setIgnore(true);

$this->addElements(array(
$firstname,
$lastname,
$username,
$email,
$password,
$password2,
$id,
$register
));
}
}


Most of the functions are simple and self explanatory. The only method that I think I’d better explain here is setIgnore() method. The method setIgnore() has a very valuable usage. Well, if we see the entire form you will feel that we need all values when form is submitted. The only value we don’t need is the value of the submit button as this only used to submit the form. We are not interested in its value, so we call setIgnore() method passing Boolean value true.

2. As we have now created a form, next step is to create its object in controller and write code that will save data for us. Create a controller as
class UsersController extends Zend_Controller_Action
{
.....

public function addAction()
{
//$this->_helper->layout->disableLayout();
$users = new Users();
$form = new CustomForm();
$this->view->form = $form;


if ($this->getRequest()->isPost()) {
$formData = $this->_request->getPost();
if ($form->isValid($formData)) {
if ($formData['password'] != $formData['password2']) {
$this->view->errorMsg = "Password and Confirm Password must match.";
$this->render('add');
return;
}
unset($formData['password2']);
unset($formData['register']);
$users->insert($formData);
}
}
}
}

What we are doing here, is pretty simple. Create an object of Users model. Well I haven’t discussed Users model yet. I would discuss it for you soon. The next line creates an object of the form created earlier. Next we assign the form to the view template, in our case the template is add.phtml.
Next few lines are of much importance.
We check whether the request is first one or the post back. If form has been submitted, method $this->getRequest()->isPost() return ture. In this case we will need to take care of the data being submitted.
To handle the post back we get the data been posted back through form, check its validity, check if the password and confirm password matches, and insert the values in the “users” table using $users->insert(); statement.
If form is not valid, the code for inserting the data in the database will not be executed.
Now lets discuss “Users” model.
We have a table in our database called “users” containing different fields such as username, firstname, lastname etc.
We will need to create our model as
class Users extends Zend_Db_Table
{
protected $_name = "users";
}


That’s it, a simple model.
3. The third step in creating a full fledge form application in Zend Framework is presentation layer, called view/template.
In your scripts/users/ directory create add.phtml and put the following code in it
<h3>Add User</h3>
<?php
if ($this->errorMsg) {
echo $this->errorMsg;
}
?>
<?php
// for displaying form
echo $this->form;
?>


The code above is self explanatory.
The above process only shows a form and submits data to the database. If you want to create edit form, you will need to make a bit of change in your controller.
Let’s create another action called editAction containing the following code.
class UsersController extends Zend_Controller_Action
{
.....

public function editAction()
{
//$this->_helper->layout->disableLayout();
$users = new Users();
$form = new CustomForm();

$id = $this->_getParam("id",1);
$select = $users->select()
->where("id = ?",$id);
$data = $users->fetchRow($select);
$form->populate($data->toArray());


if ($this->getRequest()->isPost()) {
$formData = $this->_request->getPost();
if ($form->isValid($formData)) {
if ($formData['password'] != $formData['password2']) {
$this->view->errorMsg = "Password and Confirm Password must match.";
$this->render('add');
return;
}
unset($formData['password2']);
unset($formData['register']);
//Zend_Debug::dump($formData);exit;
$users->update($formData,"id = $id");
}
}
$this->view->form = $form;
}

}

You can clearly see that I’ve made only few lines of changes.
First I get the id of the user through $this->_getParam() method. I then create a select statement on the users table and then fetch a row. Once I get the data row, I populate the form using populate() method.
The only thing you will need now, is to create a view template in your scripts/users/ directory named edit.phtml and write the following code.
<?php
if ($this->errorMsg) {
echo $this->errorMsg;
}
?>
<?php
// for displaying form
echo $this->form;
?>


Well I was thinking to explain everything in three steps, but I think it would be incomplete if I don’t explain how to show the data inserted in the database. For this reason I going to add 4th step.
4. Showing list of data
Create an action called indexAction in your controller with the following code.
class UsersController extends Zend_Controller_Action
{
public function indexAction()
{
//$this->_helper->layout->disableLayout();
$users = new Users();
$data = $users->fetchAll($users->select());
$this->view->data = $data->toArray();
//Zend_Debug::dump($data->toArray());
}

.....

}

First we create an object of our mode. And then fetch the data using the fetchAll() method. The last statement assigns the fetched data to the view template.
Now create scripts/users/index.phtml and write the following code in it.
<h4>List of users</h4>
<h5><a href="add">Add new user</a></h5>
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tboody>
<?php foreach ($this->data as $d) {?>
<tr>
<td><?=$d['firstname']?></td>
<td><?=$d['lastname']?></td>
<td><?=$d['username']?></td>
<td><?=$d['email']?></td>
<td><a href="edit/id/<?=$d['id']?>">Edit</a></td>
</tr>
<?php }?>
</tbody>
</table>

Here we are creating a table that shows the list of data. I don’t think this need to be explained.

16 comments:

  1. Hi
    It nice tutorial ... I tried this working fine. But if I put image instead of submit button it does not work. Could you suggest what thing I am doing wrong

    --
    rakesh

    ReplyDelete
  2. Hi,
    today i am geting page load error "The connection to the server was reset while the page was loading" "The network link was interrupted while negotiating a connection."

    Could you please suggest what would be the reason for this. Earlier my form is working and able to submit the process. Now when I click submit then it is returning above error.

    Thanks
    Rakesh

    ReplyDelete
    Replies
    1. It happened just bcoz u tried executing the file before the wamp server was starting its all services. The solu was to try it after some time, a minute or less..

      Delete
  3. class Users extends Zend_Db_Table

    must be

    class Users extends Zend_Db_Table_Abstract

    ReplyDelete
  4. thats great.. i have just started working in zend... and your blog is helping me alot.. thnx orakzai...Allah bless yi..

    ReplyDelete
  5. you simply expalined zend form

    Great post!!

    thnx
    Shijina T

    ReplyDelete
  6. how to Zend autoload zend_form from forms directory,
    when i try to use class from forms directory,i always receive this message:
    Fatal error: Class 'frm_User' not found in

    thank you!

    ReplyDelete
  7. how can i insert data from this??

    ReplyDelete
  8. Hey guys, check this page out http://www.songsandwords.com It's all made with Zend Framework.

    ReplyDelete
  9. Very good tutorial this has been written.A lot of effort has been done.Its has completed my task and made my day happy.thanks brother.Have successful future.
    Only problem i am facing is edit button.I have written this code in my list.phtml file.and when i click on edit then page diverts to edit/3.where 3 id my id that i selected.but then what should i do in edit function.its not working there.
    Aftab Ahmad
    Pakistan.

    ReplyDelete
  10. Hey, you have such a marvelous domain, couldn't help commenting on this one! Will you be so kind and answer my question. Is that a premium blog theme which you can buy or you used a regular one?

    ReplyDelete
  11. how to make checkbox checked after request edit which is selected at insert time

    ReplyDelete
  12. everything happens well but as i load add.phtml it doesnot show the form

    ReplyDelete
  13. I think this article will fully complement you article. PLease continue publishing helpful topics like this. Regards, from Always Open Commerce

    ReplyDelete