Cdbexception Custom Message

I have Person and Event models. A person can participate an event by selecting it from a list and both their ids are saved into a connection table.

Now , in case the person forgot that he had chosen certain event and trying to select it again , he is getting a CDbException error , which is logical , because I have both keys as unique.

However this is not user friendly. I want a message like: "You have already chosen this event" to be displayed.

Now I found many different error handling solutions , but none I tried worked (always got the standard error) and I don’t want to change the core CDbCommand because I want different errors for different models.

My logic tells me I need to change the “if-not saved” line in the person_event controller , but all I tried didn’t worked:


public function actionXcreate()

	{

		$model=new Person_Event;


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

	   {			

			foreach ($_POST['selectedIds'] as $eventId)

			{

				$pmodel=new Person_Event;

				$pmodel->person_id=$this->_person->id; 			

				$pmodel->attributes=$_POST['Person_Event'];				

				$pmodel->event_id = $eventId;				

				if (!$pmodel->save()) print_r($pmodel->errors); //<----------		

			}

			$this->redirect(array('site/contact'));

		}

Do you have a rule set up for Unique? The displayed message can be changed there.

What id printed in your if(!$pmodel->save() thing?

Are you getting a /site/error display, or is this a general exception display?

Nope , because I understood it is impossible in Yii to set unique on composite value (person_id+event_id)

I’m not sure myself what it suppose to do , but without it I don’t get any errors at all.

I get the general red titled CDbException

You should check for the record existance before saving it, but for your existing code to work, use transactions in this case or a try catch block, something like:




$transaction = Yii::app()->getDb()->beginTransaction();

try {

   // code code code [...]


   if (!$model->save()) {

       throw new Exception(CHtml::errorSummary($model), 100);

   }

   

   // code code code [...]

   $transaction->commit();

} catch (Exception $e) {

   // rollback

   $transaction->rollBack();


   // print message

   if ((int)$e->getCode() === 100) {

      // exception message is from validation so it is okay to show to the user.

      echo $e->getMessage();

   } else {

      // this can contain mysql errors, don't show to user

      echo 'Opps, something went wrong...';

   }

}



There’s no need to use a transaction if only one model is involved (just try/catch {}), only if there are multiple models dependant on each other.

It’s absolutely possible. All you need is a validator method or a custom UniqueValidator class. Chances are that an extension already exists for the latter, try a search.

I see. Actually I found this extension:

http://www.yiiframework.com/extension/composite-unique-validator/

But I don’t undestand what he means under

So far , for all the extensions I used I had to load the files to specific directories . . .

What he is saying is that you have to add the directory needs to ALSO be added to the import section of the main config file, like the Jtoggle extsion shown below:


    'import' => array(

        'application.models.*',

        'application.components.*',

        'application.extensions.jtogglecolumn.*',

    ),



Oh , I see. Made it run , but no error message is being shown when I use the composite key second time. . .

I guess I need to find other solution.

It could be that the extension you are using isn’t generating a message.

Moving extensions aside, what is the simplest way to show a message to the user instead of the sql error?

I thought to redirect him to a "failure page" , but the error jumps before the redirection happens. . .

Oh , ok , close this one.

I only now realized that I have beforeValidation function just for that . . . .

You could also use Yii::app()->setFlash();