What is the purpose of CFormModel?

I saw the following code many times


Class LoginForm extends CFormModel {...}


class ContactForm extends CFormModel

It seems every time, they want to display a form for input, they extend the CFormModel. Why this way?

I’ve already browsed CFormModel class reference, but still couldn’t understand why we need CFormModel.

One of the use I can see is to pass instance of LoginForm to CHtml::activeXXX.


<?php echo CHtml::activeLabel($form,'username'); ?>

But according to CHtml::activeLabel Class Reference, it only requires a CModel. Can we pass an CActiveRecord instance to it? CActiveRecord is just like CFormModel, a subclass of CModel.

CFormModel is used where the model data doesn’t come from an active record.

That is: it doesn’t have a related record in the database.

That’s basically it. ;)

Allow me to quote the Yii docs:

From Yii Definitive Guide - Model

I think I perfectly understand your quote. Let me refine my question. Giving three choices 1)CFormModel, 2)CForm, and 3) CHtml::Beginform() , why not just use CForm (or CHtml::Beginform() ). why we need a CFormModel to represent data?

I know my question may not make sense to you, but that’s the typical problem of beginner. They couldn’t make the distinction.

They all contain ‘xxFormxx’ which confuses me a lot~

Of course you can do that ‘manually’, but using a CFormModel is neater (in many situations) because - like an Active Record based Model, you can perform validations and enforce rules, carry functions…

Like this:


<?php

/**

 * LoginForm class.

 * LoginForm is the data structure for keeping

 * user login form data. It is used by the 'login' action of 'SiteController'.

 */

class LoginForm extends CFormModel

{

	public $username;

	public $password;

	public $rememberMe;


	private $_identity;


	/**

     * Declares the validation rules.

     * The rules state that username and password are required,

     * and password needs to be authenticated.

     */

	public function rules()

	{

		return array(

			// username and password are required

			array('username, password', 'required'),

			// rememberMe needs to be a boolean

			array('rememberMe', 'boolean'),

			// password needs to be authenticated

			array('password', 'authenticate'),

		);

	}


	/**

     * Declares attribute labels.

     */

	public function attributeLabels()

	{

		return array(

			'rememberMe'=>'Remember me next time',

		);

	}


	/**

     * Authenticates the password.

     * This is the 'authenticate' validator as declared in rules().

     */

	public function authenticate($attribute,$params)

	{

		$this->_identity=new UserIdentity($this->username,$this->password);

		if(!$this->_identity->authenticate())

			$this->addError('password','Incorrect username or password.');

	}


	/**

 	* Logs in the user using the given username and password in the model.

 	* @return boolean whether login is successful

 	*/

	public function login()

	{

//    	if($this->_identity===null)

//    	{

        	$this->_identity = new UserIdentity($this->username, $this->password);

        	if($this->_identity->authenticate()) {

            	$duration = ($this->rememberMe !== 0) ? 3600*24*30 : 0; // 30 days

            	Yii::app()->user->login($this->_identity, $duration);

            	return true;

        	} else {

            	return false;

        	}

//    	}

	}


}



Let us know if it isn’t clear.

But a CFormModel is much like a ‘regular’ model, except that there’s no active record associated with it. :)

If you don’t need any logic at all, then by all means use CHtml::form functions - they are only for presentational purposes, not data/logic.

Thanks! Using CFormModel you can accept user input data, validate, run logic on them, and store them temporary in memory in an OOP way, whereas using CForm, it’s just data array. That’s CFormModel VS CForm.

CFormModel VS CActiveRecord is that you cannot have the ‘rememberMe’ variable in CActiveRecord, since ‘rememberMe’ is not part of DB table column. Is this correct?

What if I add another attribute ‘rememberMe’ manually in CActiveRecord class, say User, and then put all user logic in User class (e.g. login() ). Do you think it will cause trouble when $user1->save() is called?

Be careful! :)

Notice this? ->


Yii::app()->user->login($this->_identity, $duration);

That is an instance of CWebUser which has a special relationship with UserIdentity - which again is acquainted with the User model…

Very confusing at first.

Read about that in the Yii Guide / API.

But essentially it allows you to track the current user through CWebUser (think session cookies) which asks CUserIdentity about the id of the user, and the login form asks CUserIdentity to authenticate:


	public function authenticate()

	{

		if (strpos($this->username,"@")) {

			$user=User::model()->notsafe()->findByAttributes(array('email'=>$this->username));

		} else {

			$user=User::model()->notsafe()->findByAttributes(array('username'=>$this->username));

		}

// More code here!!



There you can see that User::model() is asked about the attributes…

Later on, it is asked to log the user in or not. ;)

Before I confuse you even more, read this section of the guide:

http://www.yiiframework.com/doc/guide/1.1/en/topics.auth

At first, I didn’t understand the CFormModel, CUserIdentity, and CWebUser. Now I can see the way Blog Demo uses is better. Thanks!