Chapter 8 - CDbException:CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation:1062 Duplicate entry 'member'

I encountered this error at page 215/368:


$ phpunit unit/ProjectTest.php 

PHPUnit 3.5.5 by Sebastian Bergmann.


.......E


Time: 1 second, Memory: 15.75Mb


There was 1 error:


1) ProjectTest::testUserAccessBaseOnProjectRole

CDbException: CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'member-2' for key 'PRIMARY'


/var/www/YiiRoot/framework/db/CDbCommand.php:338

/var/www/YiiRoot/framework/web/auth/CDbAuthManager.php:235

/var/www/trackstar/protected/tests/unit/ProjectTest.php:140


FAILURES!

Tests: 8, Assertions: 16, Errors: 1.






    public function testUserAccessBaseOnProjectRole() {


        $row1 = $this->projUserRole['row1'];

        Yii::app()->user->setId($row1['user_id']);

        $project = Project::model()->findByPk($row1['project_id']);

        $auth = Yii::app()->authManager;

        $bizRule = 'return isset($params["project"]) && $params["project"]->isUserInRole("member");';

        $auth->assign('member', $row1['user_id'], $bizRule);

        $params = array('project' => $project);


        //check whethr can update/read/issue & update proj(FALSE of course as out of permission)

        $this->assertTrue(Yii::app()->user->checkAccess('updateIssue', $params));

        $this->assertTrue(Yii::app()->user->checkAccess('readIssue', $params));

        $this->assertFalse(Yii::app()->user->checkAccess('updateProject', $params));

    }




the line it triggered error is:


$auth->assign('member', $row1['user_id'], $bizRule);

tbl_project_user_role.php:




<?php 

return array(

    'row1'=>array(

        'project_id' => 2,

        'user_id' => 2,

        'role' => 'member',

    ),

);


?>


Project.php:

[code]<?php


/**

 * This is the model class for table "tbl_project".

 *

 * The followings are the available columns in table 'tbl_project':

 * @property integer $id

 * @property string $name

 * @property string $description

 * @property string $create_time

 * @property integer $create_user_id

 * @property string $update_time

 * @property integer $update_user_id

 */

class Project extends TrackStarActiveRecord

{

	/**

	 * Returns the static model of the specified AR class.

	 * @return Project the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'tbl_project';

	}


	/**

	 * @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('name, description, create_user_id, update_user_id', 'required'),


                        //array('name, description, create_time, create_user_id, update_time, update_user_id', 'required'),

                        //array('create_user_id, update_user_id', 'numerical', 'integerOnly'=>true),

			array('name', 'length', 'max'=>128),

			// 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'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

                    'issues' => array(self::HAS_MANY, 'Issue', 'project_id'),

                    'users' => array(self::MANY_MANY, 'User', 'tbl_project_user_assignment(project_id, user_id)'),

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'ID',

			'name' => 'Name',

			'description' => 'Description',

			'create_time' => 'Create Time',

			'create_user_id' => 'Create User',

			'update_time' => 'Update Time',

			'update_user_id' => 'Update User',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('name',$this->name,true);

		$criteria->compare('description',$this->description,true);

		$criteria->compare('create_time',$this->create_time,true);

		$criteria->compare('create_user_id',$this->create_user_id);

		$criteria->compare('update_time',$this->update_time,true);

		$criteria->compare('update_user_id',$this->update_user_id);


		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

		));

	}


        public function getUserOptions(){

            $usersArray = CHtml::listData($this->users, 'id', 'username');

            return $usersArray;

        }


        //create an association betwen the proj, the use rand user's role within the proj

        public function associateUserToRole($role, $userId){

            $sql = "INSERT INTO tbl_project_user_role (project_id, user_id, role)

                VALUES (:projectId, :userId, :role)";

            $command = Yii::app()->db->createCommand($sql);

            $command->bindValue(":projectId", $this->id, PDO::PARAM_INT);

            $command->bindValue(":userId", $userId, PDO::PARAM_INT);

            $command->bindValue(":role", $role, PDO::PARAM_STR);


            return $command->execute();

        }


        public function removeUserFromRole($role, $userId){

            $sql = "DELETE FROM tbl_project_user_role WHERE project_id=:projectId

                AND user_id=:userId AND role=:role";

            $command = Yii::app()->db->createCommand($sql);

            $command->bindValue(":projectId", $this->id, PDO::PARAM_INT);

            $command->bindValue(":userId", $userId, PDO::PARAM_INT);

            $command->bindValue(":role", $role, PDO::PARAM_STR);

            return $command->execute();//execute() returns numb of row affected

        }


        public function isUserInRole($role){

            $sql = "SELECT role FROM tbl_project_user_role WHERE project_id=

                :projectId AND user_id=:userId AND role=:role";

            $command = Yii::app()->db->createCommand($sql);

            $command->bindValue(":projectId", $this->id, PDO::PARAM_INT);

            $command->bindValue(":userId", Yii::app()->user->getId(), PDO::PARAM_INT);

            $command->bindValue(":role", $role, PDO::PARAM_STR);

            return $command->execute()==1?true:false;

        }

}

I’ve attached the screenshot of data structure and foreign keys from that table1852

yii error.tar.gz

sorry. I continue reading and find out your instruction to negate this error. The last time I just see the lines:


% phpunit unit/ProjectTest.php

...

OK (8 tests, 19 assertions)



and thought mine should’ve been like that. Anyway, it might be better if these lines is printed after the instruction - create new fixture AuthAssignment.php

how you solve the issue, please help.

thanks.

god speed.

Slightly confusing and missleading test run before setting up the fixture. Passes in the book but fails for real and then goes on to explain why it fails…even though the one in the book didn’t fail(???:frowning:???).

Anyone else gets confused by this, don’t run the test until the next page where you set up the following.

Simply add a new file to the fixtures folder

protected/tests/fixtures/AuthAssignment.php that returns an empty array.

And add the fixture to the Projecttest fixtures array.

Now run the test. Not before.

Thanks! :)