Step Five :: Enabling CRUD Operations

Creating CRUD scaffolding for projects
Once again, the Gii code generation tool is going to rescue us from having to write common, tedious and often time-consuming code. CRUD operations are such a common need of database tables created for applications that the developers of Yii decided to provide this for us. If you are familiar with other frameworks, you may know this by the term scaffolding. Let's see how to take advantage of this in Yii. Navigate back to the main Gii menu located at http://localhost/resume/index.php?r=gii, and choose the Crud Generator link. You will be presented with the following screen:
 

Here we are presented with two input form fields. The first one is asking for us to specify the Model Class against which we would like all of the CRUD operations generated. In our case, this is our Project.php AR class we created earlier. So enter Project in this field. As we do this, we notice that the Controller ID field is auto-populated with the name project, based on convention. We'll stick with this default for now. With these two fields filled in, clicking the Preview button will result in the following table being added to the bottom of the page:

 

We can see that quite a few files are going to be generated, which include a new ProjectContrller.php controller class that will house all of the CRUD action methods and many separate view files. There is a separate view file for each of them operations as well as one that will provide the ability to search project records. You can, of course, choose not to generate some of these by changing the checkboxes in the corresponding Generate column in the table. However, for our purposes, we would like Gii to create all of these for us.
Go ahead and click the Generate button. You should see the following success
message at the bottom of the page:

Creating a new project

You'll notice on this project listings page (displayed in the previous screenshot) a little navigation column in the right column block. Go ahead and click on on the Create Project link. You'll discover this actually takes us to the Login page, rather than a form to create a new project. The reason for this is that the code Gii has generated applies a rule that stipulates that only properly authenticated users
(that is, logged-in users) can create new projects. Any anonymous user that attempts to access the functionality to create a new project will be redirected to the Login page. Go ahead and log in using the credentials username as demo and password as demo.

A successful login should redirect you to the following URL:

http://localhost/resume/index.php?r=project/create

This page displays a nice input form for adding a new project, as shown in the
following figure:


Let's quickly fill out this form to create a new project. Even though none of the fields are marked as required, let's fill in the Name field as Test Project and the Description field as Test project description. Hitting the Create button will post the form data back to the server, and attempt to add a new project record. If there are any errors, a simple error message will display that highlights each field in error. A successful save will redirect to the specific listing for the newly created project. Ours was successful, and we were redirected to the page with the URL http://localhost/resume/index.
php?r=project/view&id=4, as shown in the following screenshot:



As was mentioned previously, one thing we notice about our new project creation form is that none of the fields are currently marked as being required. We can successfully submit the form without any data at all. However, we know that every project needs to have at least a name. Let's make this a required field.

Adding a required field to our form

When working with AR model classes within forms in Yii, setting validation rules around form fields is a snap. This is done by specifying values in an array set in the rules() method within the Project AR model class. Opening up the /protected/models/Project.php class reveals that this public method has already been defined, and that there are already a few rules in there:
/**
* @return array validation rules for model attributes.
*/
public function rules(){
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('create_user_id, update_user_id', 'numerical',
'integerOnly'=>true),
array('name', 'length', 'max'=>128),
array('create_time, update_time', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, name, description, create_time, create_user_id,
update_time, update_user_id', 'safe', 'on'=>'search'),
);
}

The rules() method returns an array of rules. Each rule is of the following general format:
Array('Attribute List', 'Validator', 'on'=>'Scenario List', …additional options);
The Attribute List is a string of comma separated class property names to be validated according to the Validator. The Validator specifies what kind of rule should be enforced. The on parameter specifies a list of scenarios in which the rule should be applied.

If this is not set, the rule is applied in all scenarios when save() is called. Finally, the additional options are name/value pairs, which are used to initialize the Validator's properties. The Validator can be either a method in the model class, or a separate Validator class. If defined as a model class method, it must have the following signature:

/**
* @param string the name of the attribute to be validated
* @param array options specified in the validation rule
*/
public function ValidatorName($attribute,$params) { ... }

If we use a separate class to define the Validator, that class must extend from CValidator. There are actually three ways to specify the Validator in the previously mentioned general format:
  1. One is to specify a method name in the model class itself.
  2. A second is to specify a separate class that is of a Validator type
    (that is, a class that extends CValidator). 
  3. The third manner in which you can define the Validator is by specifying a predefined alias to an existing Validator class in the Yii Framework.
Yii provides many predefined Validator classes for you and also provides aliases with which to reference these when defining rules. The complete list of predefined validator class aliases as of Yii version 1.1 is as follows:
  • boolean: Alias of CBooleanValidator, ensuring the attribute has a value that is either true or false
  • captcha: Alias of CCaptchaValidator, ensuring the attribute is equal to the verification code displayed in a CAPTCHA
  • compare: Alias of CCompareValidator, ensuring the attribute is equal to another attribute or constant
  • email: Alias of CEmailValidator, ensuring the attribute is a valid e-mail address
  • default: Alias of CDefaultVAlidator, assigning a default value to the specified attributes
  • exist: Alias of CExistValidator, ensuring the attribute value can be found in the specified table column
  • file: Alias of CFileValidator, ensuring the attribute contains the name of an uploaded file
  • filter: Alias of CFilterValidator, transforming the attribute with a filter
  • in: Alias of CRangeValidator, ensuring the data is among a pre-specified list of values
  • length: Alias of CStringValidator, ensuring the length of the data is within certain range
  • match: Alias of CRegularExpressionValidator, ensuring the data matches a regular expression
  • numerical: Alias of CNumberValidator, ensuring the data is a valid number
  • required: Alias of CRequiredValidator, ensuring the attribute is not empty
  • type: Alias of CTypeValidator, ensuring the attribute is of a specific data type
  • unique: Alias of CUniqueValidator, ensuring the data is unique in a database table column
  • url: Alias of CUrlValidator, ensuring the data is a valid URL
As we want to make the project name attribute a required field, it looks like the required alias will meet our needs. Let's add a new rule specifying this alias as the Validator to validate our project name attribute. We'll append it to the existing rules:
public function rules()
{
// NOTE: you should only define rules for those attributes that will receive user inputs.
return array(
array('create_user_id, update_user_id', 'numerical','integerOnly'=>true),
array('name', 'length', 'max'=>128),
array('create_time, update_time', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, name, description, create_time, create_user_id,update_time, update_user_id', 'safe', 'on'=>'search'),
array('name', 'required'),
);
}

By saving this file and viewing the new Project form again at: http://localhost/resume/index.php?r=project/create, we see a little red asterisk next to the Name field. This indicates that this field is now required. Try submitting the form without this field filled in. You should see an error message indicating that the Name field cannot be blank.



No comments:

Post a Comment