Now we will see the creation and working of basic forms in Yii. We will use the Gii tool to automatically generate CRUD operations and a form.
We will use the table user created in the Using the Gii tool recipe. Make sure you have enabled Gii under config/main.php
.
Generate a new model for the table
User
.Generate CRUD operations with the Gii tool as specified in the Using the Gii tool recipe.
Yii creates some new files and folders, as follows:
protected/models/User.php
: This is a model class file. It deals with database-related tasks such as fetching and storing data, updating, and deleting. TheUser
class is extended from the base classCActiveRecord
.protected/controllers/UserController.php
: This is a controller class extended from the base classController
. This class holds all the code for fetching data using models, data manipulation according to requirements, and sending data to the respective views.protected/views/user
: This folder holds views for all CRUD operations; names starting with_
are partial views that are used in multiple places. The remaining files are views for their respective action names inUserController.php
.
Let's take a look at the generated controller
file. Change access rules to enable any user to access our form as follows:
return array( //allow all users to perform 'index' and 'view' actions array('allow', 'actions'=>array('index','view', 'create'), 'users'=>array('*'), ),
All we need to do is add actionCreate()
to the actions that all users can access.
Now move to actionCreate()
. This is the action when we access the form with the URL ?r=user/create
. At the first line of actionCreate
, we instantiate the User
model. As the POST
variables are not set, the if
block is skipped and the form is rendered with the view file create
, with model
passed to it as a parameter.
public function actionCreate() { $model=new User; if(isset($_POST['User'])) { $model->attributes=$_POST['User']; if($model->save()) $this->redirect(array('view','id'=>$model->id)); } $this->render('create',array('model'=>$model)); }
In the view of create.php
, we simply render the partial view with the following lines:
<?php echo $this->renderPartial('_form', array( 'model'=>$model )); ?>
This uses the file _form.php
, which contains all the form elements and passes to it the model that we received from actionCreate
. As we need the same form elements in actionCreate
and actionUpdate
, Yii has created a single file, _form.php
, that contains all the form elements. This file is used by both the actions to render the form.
In _form.php
, we start with creating an instance of the CActiveForm
widget.
<?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'user-form', 'enableAjaxValidation'=>false, )); ?>
The HTML code in the following screenshot is created by this widget:
Next we create a space to render error details, if any, with following line:
<?php echo $form->errorSummary($model); ?>
This adds a DIV
element to the page if there are any errors in the form fields.
Next we render all necessary input elements as follows:
<div class="row"> <?php echo $form->labelEx($model,'last_name'); ?> <?php echo $form->textField($model,'last_name',array( 'size'=>50, 'maxlength'=>50, )); ?> <?php echo $form->error($model,'last_name'); ?> </div>
The HTML code generated can be seen in the following screenshot:
The $form->labelEx()
method renders the label. It takes the parameter name from the model's attributeLabels
function. If no label is set for this attribute, the attribute name is used as the label.
The $form->textField()
method renders the actual form field. We use textField
for input with the type set to text
; dropDownList
to select boxes, textArea
to render text areas, hiddenField
to render hidden fields respectively.
Note
Look at the name of the input field. It has the format User[last_name]
; this enables us to get all related form fields in a single User
array, which can be directly assigned to the models' attributes with a single line of code, $model->attributes = $_POST['User']
, thereby reducing the number of lines of code.
The $form->error()
method adds error messages in a separate div
element if there is any error with the data in this field.
Finally, we have added a submit button with the echo CHtml::submitButton('Create')
. It creates an input element with type set to submit
and is attached to the parent form by default. We can end the form widget with $this->endWidget();
.
When the user clicks on the create button, the form data is submitted to the same actionCreate
function as POST
data.
Now as the $_POST['User']
field is set, the code enters the if
block. We assign all attributes marked as safe
in the User
variable of type POST
to model with $model->attributes = $_POST['User']
. This is called Mass Assignment.
Then on the next line, we save the model with $model->save()
. The method save()
internally validates the model to check if the user has entered the valid data. Here, the rules specified in the method rules under the User
model are used to validate the form data.
public function rules() { return array( array( 'first_name, last_name, gender, dob, address_1, city, state, country, phone_number_1, email_1, created', 'required' ), array( 'first_name, last_name, city, state, country, phone_number_1, phone_number_2', 'length', 'max'=>50 ), array('gender', 'length', 'max'=>6), array( 'address_1, address_2, email_1, email_2', 'length', 'max'=>255 ), array('modified, dob', 'safe'), array( 'id, first_name, last_name, gender, dob, address_1, address_2, city, state, country, phone_number_1, phone_number_2, email_1, email_2, created, modified', 'safe', 'on'=>'search' ), ); }
In the first array, we specify all the required fields; in the next three arrays, we set the maximum length of data for each field. In the fourth array, additionally, we mark the attributes dob
and modified
as safe
. We also make several attributes as safe
when the scenario is set to search
.
If the validation is successful, the form data is persisted to the database and the page is redirected to the action view
, which displays all the captured data.
If the validation fails, the same model is passed to the view but now with the respective validation errors set in it. The line $form->errorSummary($model)
renders the summary of all errors in the form and the line $form->error()
adds the error line below the respective fields.
We have seen the automated creation of forms and CRUD operations with the Gii tool. If you want to write a custom code to process the form and you simply want to generate the form with all fields for the specified table, you can use the form generator tool provided by Gii.
Enter the model's class and view name and click on the Preview button. You will see the same form generated by the Gii tool under the views
folder. Click on the Generate button to generate the actual file.
For more information on safe attributes, visit http://www.yiiframework.com/doc/guide/1.1/en/form.model#securing-attribute-assignments.
For more information on validation rules, visit http://www.yiiframework.com/doc/guide/1.1/en/form.model#declaring-validation-rules.