Book Image

Instant Building Multi-Page Forms with Yii How-to

By : Uday Sawant
Book Image

Instant Building Multi-Page Forms with Yii How-to

By: Uday Sawant

Overview of this book

Yii is a high-performance PHP framework for rapid web application development. It is well-designed, well-supported, easy to learn, and easy to maintain. Forms are the basic method used to collect information on the Internet, and in cases like user registration and payment process, there's a lot of data to be presented and the lists can get lengthy. Instant Building Multi-Page Forms with Yii is a simple and descriptive how-to that provides step-by-step recipes to help you in converting your lengthy forms into short, interactive forms. It will guide you through the inbuilt features of Yii framework to help you with this complex job. The book starts with the basics of Yii and will guide you through creating simple forms before then converting your simple forms into multi-page forms. It will use the capabilities of Yii to ease the tasks required to do this. Yii eases your work by providing options like database connectivity. We will also take a look at the automated code generation capabilities of Yii in generating forms and necessary CRUD operations, as well as looking at how to divide a single long form into multiple views with same controller/action, and then add form validations and AJAX support to the forms. We will also cover the upload process and how to customise Yii's looks.
Table of Contents (7 chapters)

Using multiple models (Intermediate)


This recipe explains how to use multiple models within a single form.

Getting ready

We'll use the form we have developed in the Building multipage forms recipe.

Create a new table order. This will represent the orders placed by the users.

CREATE TABLE IF NOT EXISTS 'order' (
  'id' int(11) NOT NULL AUTO_INCREMENT,
  'user_id' int(11) NOT NULL,
  'product_name' varchar(255) NOT NULL,
  'quantity' int(11) NOT NULL,
  PRIMARY KEY ('id'),
  KEY 'user_id' ('user_id')
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Create a model for this table using the Gii tool.

How to do it...

Let's add this new model to the actionCreate method developed for multiple forms. We will need to add one more step/page to the action as follows:

...
$this->checkPageState($model, Yii::app()->request->getPost('User',array()));
$this->setPageState('order', Yii::app()->request->getPost('Order', array()));
...
...
if($model->validate())
{
  $view = '_page4';
  $order = new Order();
  $order->attributes = $this->getPageState(
    'order', array()
  );
}
...

else if(isset($_POST['submit']))
{
  $model = new User('page3');
  $order = new Order();
  $model->attributes = $this->getPageState(
    'page', array()
  );
  $order->attributes = $_POST['Order'];
  if($model->validate())
  {
    $model->save();
    $order->user_id = $model->id;
    if($order->validate())
    {
      $order->save();
      $this->redirect(array('view', 'id'=>$model->id));
    }
  }
  $view = '_page4';
}

Next, create a view for _page4.

...
<div class="row">
  <?php echo $form->labelEx($order,'product_name'); ?>
  <?php echo $form->textField($order,'product_name'); ?>
  <?php echo $form->error($order,'product_name'); ?>
</div>
<div class="row">
  <?php echo $form->labelEx($order,'quantity'); ?>
  <?php echo $form->numberField ($order,'quantity'); ?>
  <?php echo $form->error($order,'quantity'); ?>
</div>
<div class="row buttons">
  <?php echo CHtml::submitButton('Back', array(
    'name'=>'page3')); ?>
  <?php echo CHtml::submitButton('submit', array(
    'name'=>'submit')); ?>
</div>
...

Change the submit button in the view of _page3 to the following:

<?php echo CHtml::submitButton('Next', array(
  'name'=>'page4'
)); ?>

We are done; try the new form in your browser. It will look something like the following screenshot:

How it works...

We introduced an order model in the fourth page of our multipage form with the following code:

if($model->validate())
{
  $view = '_page4';
  $order = new Order();
  $order->attributes = $this->getPageState('order', array());
}

First we check if the data we received in the third step for the model User is valid. If the model validates, we set our view page to _page4. Then we create a new model named Order. On the third line, we simply check if there's any saved state for the model Order; this is useful if the user moves back after filling the data of Order.

In the same way, we have added some code in the third step to check if the user has moved back from _page4 after filling the form fields. So we save the current state of _page4. Notice the use of Yii::app()->request->getPost('User', array()) line of code. The getPost() method is used to get the named POST value. The first parameter is the name of the POST field and the second parameter is the default value if the POST field with the given name is not set. Similarly, you can use the getParam() method to get the parameters of GET.

Next, in the final step, we assign the saved state to the User model, and $_POST data to the Order model. As we have already loaded a save state on the page, $_POST will hold the updated data (if any) or the data in that saved state.

Then we validate the User model with if($model->validate()). After successful validation, we save the User model and assign the user's ID to the Order model with $order->user_id = $model->id. Then we save the Order model too. If it's successful, we redirect to view the page; else, we redirect to the fourth page to solve the form errors.

There's more...

We could use the transactional feature of the database while storing the data; that is, if the saving of the order model fails, we could discard the User model entirely by rolling back the transaction as follows:

if($model->validate())
{
  $transaction = Yii::app()->db->beginTransaction();
  try
  {
    $model->save();
    $order->user_id = $model->id;
    if(!$order-> save())
      throw new Exception('Order data invalid'); 
    $transaction->commit();
    $this->redirect(array('view', 'id'=>$model->id));
  }
  catch(Exception e)
  {
    $transaction->rollBack();
    $view = 'page4';
  }
}

For more details on database transaction visit the website en.wikipedia.org/wiki/Database_transaction.

Transactional queries support in Yii can be looked up on the website http://www.yiiframework.com/doc/guide/1.1/en/database.dao#using-transactions.