CDbException Chapter 8

Hi,

I am at about page 191 in the book i.e. I have just used the Interactive tool to run Rbac.

Now I logged into my account and got this CDbException error. I have no idea if it’s related to the Rbac stuff that I’m working on at this point in the book… It may be this error has existed for a while and I didn’t notice it because everything else seems to work, i.e. I can view projects and issues etc.

Also, note, while it gives me this error, it still logs me in, but I obviously don’t want the error. If it’s relevant this is my database set up from /config/main.php


'db'=>array(

			'connectionString' => 'mysql:host=127.0.0.1;port=8889;dbname=trackstar_dev',

			'emulatePrepare' => true,

			'username' => 'root',

			'password' => 'root',

			'charset' => 'utf8',

		),

Can anyone help?


04:21:57.328758	error	exception.CDbException	

exception 'CDbException' with message 'No columns are being updated for

table "tbl_user".' in

/Applications/MAMP/htdocs/framework/db/schema/CDbCommandBuilder.php:266

Stack trace:

#0 /Applications/MAMP/htdocs/framework/db/ar/CActiveRecord.php(1650):

CDbCommandBuilder->createUpdateCommand(Object(CMysqlTableSchema), Array,

Object(CDbCriteria))

#1 /Applications/MAMP/htdocs/demo/protected/models/LoginForm.php(73):

CActiveRecord->updateByPk('1', Array)

#2

/Applications/MAMP/htdocs/demo/protected/controllers/SiteController.php(88):

LoginForm->login()

#3 /Applications/MAMP/htdocs/framework/web/actions/CInlineAction.php(50):

SiteController->actionLogin()

#4 /Applications/MAMP/htdocs/framework/web/CController.php(300):

CInlineAction->runWithParams(Array)

#5 /Applications/MAMP/htdocs/framework/web/CController.php(278):

CController->runAction(Object(CInlineAction))

#6 /Applications/MAMP/htdocs/framework/web/CController.php(257):

CController->runActionWithFilters(Object(CInlineAction), Array)

#7 /Applications/MAMP/htdocs/framework/web/CWebApplication.php(328):

CController->run('login')

#8 /Applications/MAMP/htdocs/framework/web/CWebApplication.php(121):

CWebApplication->runController('site/login')

#9 /Applications/MAMP/htdocs/framework/base/CApplication.php(155):

CWebApplication->processRequest()

#10 /Applications/MAMP/htdocs/demo/index.php(13): CApplication->run()

#11 {main} REQUEST_URI=/demo/index.php/site/login

04:21:57.332751	trace	system.CModule	

Loading "errorHandler" application component




Could you post the contents of

/Applications/MAMP/htdocs/demo/protected/models/LoginForm.php

and

/Applications/MAMP/htdocs/demo/protected/components/UserIdentity.php

and

/Applications/MAMP/htdocs/demo/protected/controllers/SiteController.php - just the actionLogin() part

I don’t understand. Do you just want me to post the files … Here they are. Thanks for helping.

LoginForm.php


<?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)

	{

		if(!$this->hasErrors())

		{

			$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);

			$this->_identity->authenticate();

		}

		if($this->_identity->errorCode===UserIdentity::ERROR_NONE)

		{

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

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

			User::model()->updateByPk($this->_identity->id, array('last_

login_time'=>new CDbExpression('NOW()')));

			return true;

		}

		else

			return false;

	}

}



User Identity.php




<?php

/**

 * UserIdentity represents the data needed to identity a user.

 * It contains the authentication method that checks if the provided

 * data can identify the user.

 */

class UserIdentity extends CUserIdentity

{

    private $_id;


    /**

	 * Authenticates a user using the User data model.

	 * @return boolean whether authentication succeeds.

	 */

    public function authenticate()

    {

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

        if($user===null)

        {

			$this->errorCode=self::ERROR_USERNAME_INVALID;

	    }

        else 

        {

	        if($user->password!==$user->encrypt($this->password))

	        {

				$this->errorCode=self::ERROR_PASSWORD_INVALID;

			}

        	else

        	{

            	$this->_id = $user->id;

            	if(null===$user->last_login_time)

            	{

					$lastLogin = time();

				}

	        	else

	        	{

					$lastLogin = strtotime($user->last_login_time);

				}

	        	$this->setState('lastLoginTime', $lastLogin); $this->errorCode=self::ERROR_NONE;

			}

        }

        return !$this->errorCode;

    }

 

    public function getId()

    {

        return $this->_id;

    }


}

Site Controller.php




<?php


class SiteController extends Controller

{

	/**

	 * Declares class-based actions.

	 */

	public function actions()

	{

		return array(

			// captcha action renders the CAPTCHA image displayed on the contact page

			'captcha'=>array(

				'class'=>'CCaptchaAction',

				'backColor'=>0xFFFFFF,

			),

			// page action renders "static" pages stored under 'protected/views/site/pages'

			// They can be accessed via: index.php?r=site/page&view=FileName

			'page'=>array(

				'class'=>'CViewAction',

			),

		);

	}


	/**

	 * This is the default 'index' action that is invoked

	 * when an action is not explicitly requested by users.

	 */

	public function actionIndex()

	{

		// renders the view file 'protected/views/site/index.php'

		// using the default layout 'protected/views/layouts/main.php'

		$this->render('index');

	}


	/**

	 * This is the action to handle external exceptions.

	 */

	public function actionError()

	{

	    if($error=Yii::app()->errorHandler->error)

	    {

	    	if(Yii::app()->request->isAjaxRequest)

	    		echo $error['message'];

	    	else

	        	$this->render('error', $error);

	    }

	}


	/**

	 * Displays the contact page

	 */

	public function actionContact()

	{

		$model=new ContactForm;

		if(isset($_POST['ContactForm']))

		{

			$model->attributes=$_POST['ContactForm'];

			if($model->validate())

			{

				$headers="From: {$model->email}\r\nReply-To: {$model->email}";

				mail(Yii::app()->params['adminEmail'],$model->subject,$model->body,$headers);

				Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');

				$this->refresh();

			}

		}

		$this->render('contact',array('model'=>$model));

	}


	/**

	 * Displays the login page

	 */

	public function actionLogin()

	{

		$model=new LoginForm;


		// if it is ajax validation request

		if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}


		// 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->redirect(Yii::app()->user->returnUrl);

		}

		// display the login form

		$this->render('login',array('model'=>$model));

	}


	/**

	 * Logs out the current user and redirect to homepage.

	 */

	public function actionLogout()

	{

		Yii::app()->user->logout();

		$this->redirect(Yii::app()->homeUrl);

	}

}

The issue appears to be with this line in your LoginForm:


User::model()->updateByPk($this->_identity->id, array('last_login_time'=>new CDbExpression('NOW()')));

For some reason, it looks like an empty array is being sent to the updateByPk method:

1 /Applications/MAMP/htdocs/demo/protected/models/LoginForm.php(73):

CActiveRecord->updateByPk(‘1’, Array)

Or, perhaps the column ‘last_login_time’ changed name or does not exist in your tbl_user table?

Thank you for directing me to the problem area. There was somewhite space in the name of


last_ login_time