PHP Development Framework YII Framework Tutorial (8) using Formmodel

Source: Internet
Author: User
Tags valid email address yii
Through previous studies, we learned about the basic components of YII Web applications and also wrote simple applications like hangman guessing word games. In the first example Yii Framework development Concise Tutorial (1) The first app Hello world we introduced the YII Web application using the MVC model, and also explained that this tutorial is intended to be a different perspective (mainly through the development of Windows app c++,c# Programmer's perspective) to help Windows desktop apps or ASP. NET programmers get a quick grasp of the PHP YII Framework application Framework.

Earlier we introduced the creation of view through cHTML (Page view Form), the use of Ccontroller to handle user-submitted events, and the Windows desktop app or the ASP. A page similar to WinForm or ASP. The control class controller is similar to a Windows desktop app or an ASP. Net event handling (Code-behind) class. The difference is that ASP. NET and Windows desktop apps can define IDs for individual UI components in the UI, such as text boxes, buttons, and then add event handling for different UI components. There is no mechanism for PHP applications or YII applications to define an ID for the UI component defined in the HTML form and to define event handling for the UI component. The YII framework, however, provides cformmodel support for similar functions, simply speaking, by Cformmodel, you can define variables for UI widgets in HTML Form, and you can access them in their control class controller. Each yii View (Form) generally provides a "submit" button (submit button), the user click on the "Submit buttons" trigger Ccontroller object corresponding to the Actionxxx method, in Actionxxx The Cformmodel method can be used to access the value of the UI component of an HTML form.

As mentioned in the previous tutorial, the model in Yii is an instance of CModel or its subclasses. Models are used to persist data and the business logic associated with it,

YII implements two types of models: the form model and the Active Record. Both inherit from the same base class CModel.

The form model is an instance of Cformmodel. The form model is used to keep the data obtained from the user's input. These data are often acquired, used, and then discarded. For example, on a login page, we can use the form model to represent the user name and password information provided by the end user. For more information, please refer to using the form. This article describes the use of Cformmodel,

Active Record (AR) is a design pattern used to abstract database access through object-oriented styles. Each AR object is an instance of a Cactiverecord or its subclasses. Represents a row in a data table. The fields in the row correspond to the properties in the AR object. For more details on AR please read the Active Record. The following describes how the database is used.

This article uses a simple login interface to introduce the use of Formmodel, which is downloaded in this example.

1. Defining Model Classes

Below we create a loginform (protected/models/loginform.php) model class that collects input from users on a single login page. Because the login information is only used to authenticate the user and does not need to be saved, we create the loginform as a form model.

Class LoginForm Extendscformmodel    {public        $username;        public $password;        Public $rememberMe =false;    }

2. Declaring validation rules
Once the user submits his input and the model is populated, we need to make sure that the user's input is valid before use. This is done by validating the user's input and a series of rules. We specify these validation rules in the Rules () method, and this method should return a rule configuration array.

Class LoginForm extends Cformmodel    {public        $username;        public $password;        Public $rememberMe =false;                Private $_identity;                Public function rules ()        {            return array (                ' username, password ', ' required '),                array (' RememberMe ' , ' Boolean '),                Array (' Password ', ' Authenticate '),            );                Public function Authenticate ($attribute, $params)        {            $this->_identity=new useridentity ($this Username,                  $this->password);            if (! $this->_identity->authenticate ())                $this->adderror (' password ', ' wrong user name or password. ');        }    }

The above code specifies that: username and password are required, password should be validated (authenticated), and RememberMe should be a Boolean value.

Each rule returned by the rules () must be in the following format:

Array (' AttributeList ', ' Validator ', ' on ' = ' scenariolist ', ... Additional options)

where AttributeList (attribute list) is an attribute list string that needs to be validated by this rule, each attribute name is separated by commas; The Validator (validator) specifies the kind of validation to perform; the on parameter is optional, which specifies the list of scenes to which this rule should be applied; an additional option is an array of name values that initializes the property values of the corresponding validator.

There are three ways to specify Validator in validation rules. First, Validator can be the name of a method in a model class, just like the authenticate in the example above. The validation method must be the following structure:

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

Second, Validator can be the name of a validator class, and when this rule is applied, an instance of a validator class is created to perform the actual validation. Additional options in the rule are used to initialize the property values of the instance. The validator class must inherit from Cvalidator.

Third, Validator can be an alias for a predefined validator class. In the example above, the required name is the alias of Crequiredvalidator, which is used to ensure that the attribute value being validated is not NULL. The following is a complete list of predefined authenticator aliases:

The alias of the Boolean:cbooleanvalidator to ensure that the attribute has a cbooleanvalidator::truevalue or cbooleanvalidator::falsevalue value.

Captcha:ccaptchavalidator, ensure that the attribute value is equal to the verification code shown in Captcha.

The alias of the Compare:ccomparevalidator to ensure that the attribute equals another attribute or constant.

Email:cemailvalidator alias, ensure that the feature is a valid email address.

An alias for the default:cdefaultvaluevalidator that specifies the default value for the attribute.

Exist:cexistvalidator, make sure that the attribute values can be found in the columns of the specified table.

File:cfilevalidator alias, make sure that the feature contains a name for the uploaded file.

The alias of Filter:cfiltervalidator, which changes this feature through a filter.

The alias of the In:crangevalidator to ensure that the data is within the range of a pre-specified value.

The alias of the Length:cstringvalidator to ensure that the length of the data is within a specified range.

The alias of the Match:cregularexpressionvalidator to ensure that the data can match a regular expression.

The alias of the Numerical:cnumbervalidator to ensure that the data is a valid number.

The alias of the Required:crequiredvalidator to ensure that the attribute is not empty.

The alias of the Type:ctypevalidator to ensure that the attribute is the specified data type.

The alias of the Unique:cuniquevalidator to ensure that the data is unique in the data table column.

The alias of the Url:curlvalidator to ensure that the data is a valid URL.

Here are a few examples of these pre-defined validators:

User name is required    Array (' username ', ' required '),    //username must be between 3 and 12 characters in    Array (' username ', ' length ', ' min ' =>3, ' Max ' =>12),    //In the registration scenario, the password password must be consistent with PASSWORD2.    Array (' password ', ' compare ', ' compareattribute ' = ' password2 ', ' on ' = ' register '),    //In the login scenario, the password must be validated.    Array (' Password ', ' Authenticate ', ' on ' = ' login '),

3. Security-Specific value assignment

After an instance of a class is created, we usually need to populate its attributes with the data submitted by the end user. This can be done easily with the following block assignment (massive assignment):

$model =new LoginForm;
if (Isset ($_post[' loginform '))
$model->attributes=$_post[' LoginForm '); the last expression is called a block assignment (massive assignment), which will $_post[' LoginForm ' copied into the corresponding model attribute. This is equivalent to the following assignment method:

foreach ($_post[' LoginForm ') as $name + = $value)    {        if ($name is a security feature)            $model $name = $value;    }

It is important to detect the security of an attribute, for example, if we assume that the primary key of a table is safe and expose it, then an attacker could gain an opportunity to modify the record's primary key, thereby tampering with the content that was not authorized to him.

The policy for detecting feature security is different in versions 1.0 and 1.1, which we will explain separately below:

Security features in 1.1

In version 1.1, an attribute is considered safe if it appears in a validation rule in the appropriate scenario. For example:

Array (' Username, password ', ' required ', ' on ' = ' login, register '),
Array (' email ', ' required ', ' on ' = ' register '), as shown above, the username and password features are required in the login scenario. The username, password, and email features are required in the register scenario. So, if we execute the block assignment in the login scene, only username and password will be assigned to the block. Because only they appear in the validation rules of login. On the other hand, if the scene is a register, these three attributes can all be assigned to a block.

    $model =new User (' login ') in the login scenario;    if (Isset ($_post[' user '))        $model->attributes=$_post[' user '];    $model =new User (' register ') in the registration scenario;    if (Isset ($_post[' user '))        $model->attributes=$_post[' user '];

So why do we use such a strategy to detect the security of a feature? The rationale behind this is this: If a feature already has one or more validation rules that can detect validity, what are we worried about?

Keep in mind that validation rules are used to check the data entered by the user, rather than checking the data we generate in the code (such as timestamps, auto-generated primary keys). Therefore, do not add validation rules for attributes that do not accept end-user input.

Sometimes we want to declare that a feature is safe, even if we don't specify any rules for it. For example, the content of an article can accept any input from the user. We can use special safe rules to do this:

Array (' content ', ' safe ')

For the sake of completion, there is an unsafe rule that declares a property to be unsafe:

Array (' permission ', ' unsafe ')

Unsafe rules are not commonly used and are an exception to the security features we defined earlier.

Security Features in 1.0

In version 1.0, determine whether a data item is secure, based on a return value called the Safeattributes method and the scene specified by the data item. By default, this method returns all public member variables as the security attribute of the Cformmodel, and it also returns the security attributes of all field names in the table, except the primary key, as Cactiverecord. We can override this method to restrict security features based on the scenario. For example, A user model can contain many features, but in the login scenario, we can only use the username and password features. We may specify this limit as follows:

Public Function safeattributes ()    {        return Array (            parent::safeattributes (),            ' login ' = ' username ', Password ',        );    } The more accurate return value of the Safeattributes method should be structured as follows: Array (       //These attributes can be massively assigned in any scenario       //So is Not explicitly specified below       ' attr1, attr2, ... ',         *       //These attributes can be massively assigned only in S Cenario 1       ' scenario1 ' = ' attr2, ATTR3, ... ',         *       //These attributes can be massively assigned @ SC Enario 2       ' scenario2 ' = ' attr1 ', ATTR3, ... ',    )

If the model is not scene-sensitive (for example, it is used only in one scene, or if all the scenes share a set of identical security features), the return value can be a simple string like the following.

' Attr1, attr2, ... '

For those insecure data items, we need to use separate assignment statements to assign them to the corresponding attributes. As shown below:

$model->permission= ' admin ';    $model->id=1;4. Trigger validation

Once the model is populated with data submitted by the user, we can invoke the Cmodel::validate () departure data validation process. This method returns a value that indicates whether the validation was successful. For the Cactiverecord model, validation can also be triggered automatically when we call its Cactiverecord::save () method.

We can use scenario to set the scene properties so that the validation rules for the corresponding scene will be applied.

Validation is performed based on the scene. The Scenario property specifies the scene currently used by the model and the set of validation rules currently in use. For example, in the login scenario, we only want to validate the username and password inputs in the user model, and in the register scenario, we need to verify more input, such as email, address, and so on. The following example shows how to perform validation in the Register scenario:

//create a User model in the registration scenario.    Equivalent to://$model =new User;    $model->scenario= ' register ';            $model =new User (' register ');            Populate the model with the input values $model->attributes=$_post[' User '; Perform validation if ($model->validate ())//If the inputs is valid ... else ... The scene associated with the rule can be specified by the ON option in the rule. If the on option is not set, the rule is applied to all scenarios. For example: Public function rules () {return Array (' username, password ', ' required '), Array (        ' Password_repeat ', ' required ', ' on ' = ' register '), Array (' Password ', ' compare ', ' on ' = ' register '),    ); }

The first rule will be applied to all scenarios, and the second will only apply to the register scene.

5. Extract validation error

When validation is complete, any errors that may be generated will be stored in the model object. We can extract these error messages by calling Cmodel::geterrors () and Cmodel::geterror (). The difference between the two methods is that the first method returns error information for all model attributes, and the second returns only the first error message.

6. Attribute Tags

When designing a form, we typically need to display a label for each form field. The tag tells the user what information he should fill out in this form field. Although we can hardcode a label in the view, it is more flexible and convenient if we specify (label) in the corresponding model.

By default CModel will simply return the name of the attribute as its label. This can be customized by overriding the Attributelabels () method. As we'll see in the next sections, assigning tags in the model will allow us to create more powerful forms faster.

7. Create an Action action method

Once the LoginForm form model is created, we can write the user-submitted processing code for it (corresponding to an action method in the controller). This example uses the default Sitecontroller, and the corresponding action is actionlogin.

Public Function Actionlogin ()    {        $model =new loginform;        Collect user input data        if (isset ($_post[' loginform '))        {            $model->attributes=$_post[' loginform '];            Validate user input and redirect to the previous page if valid            if ($model->validate () && $model->login ()) {                        $this->render (' index ');                return;            }        }        Display the login form        $this->render (' login ', array (' model ' = ' $model) ');    

As shown above, we first created an example of a loginform model, and if the request is a POST request (which means that the login form was submitted), we populate the $model with the submitted data $_post[' LoginForm '), and then we validate the input, If the validation succeeds, the index page is displayed. If the validation fails, or if the action is first accessed, we render the login view.
Note that we have modified the default action for Sitecontroller to login.

/**    * @var string sets the default action to be ' login '    */public $defaultAction = ' login ';

So the first page that the user sees is the login page instead of the index page, and only if the user enters the correct user name, this example uses a fixed user name and password, see the Useridentity class definition, the actual application can read the database or the LDAP server.

/** * Useridentity represents the data needed to identity a user.    * It contains the authentication method that checks if the provided * data can identity the user.        */class Useridentity extends Cuseridentity {/** * authenticates a user.        * The example implementation makes sure if the username and password * are both ' demo '.  * In practical applications, this should is changed to authenticate * against some persistent user identity storage        (e.g. database).        * @return Boolean whether authentication succeeds.                */Public Function authenticate () {$users =array (//username = password            ' Demo ' = ' demo ', ' admin ' = ' admin ', ';            if (!isset ($users [$this->username]) $this->errorcode=self::error_username_invalid; else if ($users [$this->username]!== $this->password) $this->errorcode=self:: Error_password_invalid;            else $this->errorcode=self::error_none;        Return! $this->errorcode; }    }

Let's pay special attention to the following PHP statement that appears in the login action:

$model->attributes=$_post [' LoginForm '];

As we said in the Secure attribute assignment, this line of code populates the model with user-submitted data. The Attributes property is defined by Cmodel, which accepts an array of name values and assigns each value to the corresponding model attribute. So if $_post [' loginform '] gives us an array like this, the code above is equivalent to the lengthy paragraph (assuming all the required attributes exist in the array):

$model->username=$_post[' loginform ' [' username ']; $model->password=$_post [' loginform '] [' Password '];$ model->rememberme=$_post[' LoginForm '] [' rememberme '];

8. Building a View

Writing the login view is simple, and we start with a form tag whose Action property should be the URL of the login action described earlier. Then we need to insert labels and form fields for the attributes declared in the LoginForm class. Finally, we insert a submit button that can be clicked by the user to submit this form. All of this can be done with pure HTML code.

YII provides several helper (helper) classes for simplified view writing. For example, to create a text input field, we can call Chtml::textfield (); To create a drop-down list, call CHtml::d ropdownlist ().

Info: You may want to know the benefits of using an assistant if they need the same amount of code as the amount of code that writes pure HTML directly. The answer is that the helper can provide more functionality than the HTML code. For example, the following code generates a text input field that can touch the post-commit action when the user modifies its value.

Chtml::textfield ($name, $value, Array (' submit ' = ') ');

Otherwise you'll need to write a lot of JavaScript.

Below, we use CHtml to create a login form. We assume that the variable $model is an instance of LoginForm.

<center class= "form" > <?php echo chtml::beginform ();?> <?ph P Echo chtml::errorsummary ($model);?> <center class= "Row" > <?php echo Chtml::activelabel ($model, ' Us Ername ');?> <?php Echo Chtml::activetextfield ($model, ' username ')?> </center> <cen ter class= "Row" > <?php echo Chtml::activelabel ($model, ' password ');?> <?php echo CHtml:: Activepasswordfield ($model, ' password ')?> </center> <center class= "Row RememberMe" > &L t;? PHP echo Chtml::activecheckbox ($model, ' rememberme ');?> <?php Echo Chtml::activelabel ($model, ' RememberMe ' );?> </center> <center class= "row Submit" > <?php echo Chtml::submitbutton (' Login ') ;?> </center><?php Echo chtml::endform ()?> </center><!--form--> 

The code above generates a more dynamic form, for example, Chtml::activelabel () generates a label that is related to the characteristics of the specified model. If this attribute has an input error, the CSS class of this tag becomes error, and the CSS style changes the appearance of the label. Similarly, Chtml::activetextfield () generates a text input field for the properties of the specified model and changes its CSS class when an error occurs.

If we use a CSS style file provided by the YIIC script, the resulting form will look like this:

CSS styles are defined in the CSS directory, this example uses the YII default style.

Starting with version 1.1.1, a new small object cactiveform is provided to simplify form creation. This small object can provide both client and server-side seamless, consistent validation. With Cactiveform, the above code can be rewritten as:

<center class= "Form" > <?php $form = $this->beginwidget (' cactiveform ');?> <?php Echo $f Orm->errorsummary ($model);?> <center class= "Row" > <?php echo $form->label ($m                 Odel, ' username ');?> <?php echo $form->textfield ($model, ' username ')?> </center> <center class= "Row" > <?php echo $form->label ($model, ' password ');?> <?p HP Echo $form->passwordfield ($model, ' password ')?> </center> <center class= "Row Reme Mberme "> <?php echo $form->checkbox ($model, ' rememberme ');?> <?php Echo $form->lab El ($model, ' rememberme ');?> </center> <center class= "row Submit" > <?ph P Echo Chtml::submitbutton (' Login ');?> </center> <?php $this->endwidget ();?> &lt ;/center><!--Form - 

The UI components supported by the YII framework, including the use of Cactiveform, are described individually from the beginning of the next chapter.

The above is the PHP Development Framework YII Framework Tutorial (8) Use Formmodel content, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.