Foreign Key Constraints

How can I handle foreign key constraints in my app? I have an ON DELETE RESTRICT constraint. At the moment I get a CDbException when I try to delete a record - I presume I need to catch the exception somehow? Sorry I’m not too clued up in this area!

Also the CGridView will need to handle the constraint via the AJAX delete call - can a flash message be displayed?

Someone had the same problem and posted a solution here:

http://www.yiiframew…-key-constraint

Sounds reasonable ;)

Thanks for that. I’ve done it like this:


try

{

	$this->loadModel()->delete();

	Yii::app()->user->setFlash('success', "The User has been deleted successfully.");

}

catch(CDbException $e)

{

	Yii::app()->user->setFlash('error', "The User could not be deleted.");

}

This works fine and the flash message is displayed on the normal delete, but how do I get it to display a flash message on the AJAX delete?

take inspiration from this.

There is CGridView::afterAjaxUpdate for execute the js code you have.

Right, so basically with the AJAX delete we don’t send a ‘flash’ message but instead it should be a CJSON response? Man, I can’t get my head around this. I have done it like this:

Controller:


try

{

	$this->loadModel()->delete();

	Yii::app()->user->setFlash('success', "The User has been deleted successfully.");

}

catch(CDbException $e)

{

	Yii::app()->user->setFlash('error', "The User could not be deleted.");

			

	echo CJSON::encode(array(

		'message'=>"The User could not be deleted.",

	));

				

	exit; 

}

CGridView:


'afterAjaxUpdate'=>"function setFlash(id, data) {

	$('.flash-error').html(data).fadeIn().animate({opacity: 1.0}, 3000).fadeOut('slow');

}",

And I have created a hidden div with class ‘flash-error’.

Well, I am not 100% sure that is possible to do it.

I successfully did such kind of flash messages in ajax, the trick is to include in the ajax response some javascript code that displays the flash message.

In my example, in case of ajax response I send back a json array with 2 fields, the html to relplace and the flash message.

Your case is more difficoult, because you are working with CGridView, wich complicates the situation.

Maybe a very rogue solution can be to write, in case of exception, some javascript directly in the cell of the cgridView, something like:




<script type="text/javascript">

setFlash('success', 'The User could not be deleted.');

</script>




This script should be echoed INSIDE the grid view, so when CGridView will replace the table, you will get the flash.

Thanks zaccaria but I am still struggling with this. Anybody got any more ideas?

Hi G-Star,

If you are going to flush a JSON response, you should not forget to include the " dataType:‘json’ " in your ajax call. Then you will be able to:

‘afterAjaxUpdate’=>"function setFlash(id, data) {

    &#036;('.flash-error').html(data.[color=&quot;#FF0000&quot;]message[/color]).fadeIn().animate({opacity: 1.0}, 3000).fadeOut('slow');

}",

If I do ajax calls, I do not use setFlash-getFlash at all. I do receive the JSON or string responses from the server and work with them accordingly.

Where do I put that? The ‘delete’ ajax call is one that is built-in to the CGridView, i.e. the jQuery code is auto-generated as follows:


jQuery('#user-grid a.delete').live('click',function() {

	if(!confirm('Are you sure you want to delete this item?')) return false;

	$.fn.yiiGridView.update('user-grid', {

		type:'POST',

		url:$(this).attr('href'),

		success:function() {

			$.fn.yiiGridView.update('user-grid');

		}

	});

	return false;

});

Here buddy:





jQuery('#user-grid a.delete').live('click',function() {

        if(!confirm('Are you sure you want to delete this item?')) return false;

        $.fn.yiiGridView.update('user-grid', {

                type:'POST',

                dataType: 'json', // <---- here

                url:$(this).attr('href'),

                success:function() {

                        $.fn.yiiGridView.update('user-grid');

                }

        });

        return false;


});




That’s all good bro but that code is auto-generated by CGridView, I’m not sure where to edit it and how to make the CGridView use the new code.

Can i see your CGridView code before rendering?

if you use an ajax button:

public static string ajaxButton(string $label, mixed $url, array $ajaxOptions=array ( ), array $htmlOptions=array ( ))

in the $ajaxOptions array you do array(‘dataType’=>‘json’)

I just dont know what are you doing for firing the ajax call…

Its just the standard CGridView - I haven’t configured it in any special way. The delete button is part of the CButtonColumn and this auto-generates the jQuery function I posted above. The only way I can think of putting in the ‘dataType’=>‘json’ is by editing the core framework file.

Then dont use JSON. Simply echo your error message!

And receive it as you exposed before. Is as simple as that, try it and you’ll see.

Please refer to the comments in this page: http://www.yiiframework.com/doc/api/1.1/CButtonColumn

Youll see how to setup the buttons individually. Maybe is best to make the button call a function on click that makes the correspondent ajax actions and handles its response.

OK, for testing purposes I edited the CButtonColumn.php file and inserted ‘dataType’=>‘json’ in the jQuery delete function.

It did not make any difference. I then added an alert(data.message) to my afterAjaxUpdate function and it outputs ‘undefined’.

‘message’ gets defined in the controller delete action via the CJSON::encode, in theory anyway.

BUMP. Any ideas anyone?

What do you see in Firebug Console?

/Tommy

I don’t get any errors in Firebug, I get one POST request and one GET request, the POST request receives a JSON response with:

{"message":"The User could not be deleted."}

I know that my afaterAjaxUpdate function is working because if I do

$(’.flash-error’).html(‘test’)

This outputs correctly. For some reason it can’t capture data.message

Previously, in the success handler of the POST request you execute another call to $.fn.yiiGridView.update(‘user-grid’). (Default method is GET.)

Is it still there? Try removing it to see if the message will show up.

/Tommy