Yii Framework Forum

Notify if similar record exists


(Rossmccaughrain) #1

Hi All,

Im trying to create a football site where an admin user can add new players. I want to ensure I dont get the same player entered twice (although unlikely in a small team there could be an instance when 2 players have the same name). What I want to do is when a user is creating a new player check to see if there already exists a record with the "Firstname+Surname" and then prompt the user saying:

"There already exists a player with name "Firstname Surname" do you want to continue adding this player? Yes/No

If they select Yes continue adding the player, if they select No redirect to the matching players update screen

I know to do this in a straight PHP form id use the onSubmit and call an ajax function which would do the db lookup and return true or false (etc) but im not sure of the best way to go about it in Yii. Should i use the CActiveForm beforeValidate/AfterValidate? But this means i have to enable AjaxValidation?

My Form/Model/CRUD have all been generated using Gii so ive nothing fancy in them.

Any help would be greatly appreciated.

Many thanks

Ross


(Rossmccaughrain) #2

Ok so im stuck and frustrated now. I have tried to break it down into simply steps but no matter what i return from my afterValidate (or beforeValidate for that matter) true or false it doesnt proceed with the form submission. Any ideas anyone?

In my view:




<script type="text/javascript">

	function afterValidate(form, data, hasError){

		$.ajax({

			data: $("#club-members-form").serialize(),

			url: "<?php echo $this->createUrl('CheckDuplicate');?>",

			cache: false,

			success: function(data) {

				return true;

                                /*if(data == null || data.length == 0) {

					alert('Here');

					return false;

				}

				else {

					$("#possibleDuplicate").html(data);

					$("#possibleDuplicateDialog").dialog("open");

				}*/

			}

		});

	}

</script>


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'club-members-form',

	'enableAjaxValidation'=>false,

	'enableClientValidation'=>true,

	'focus'=>array($model,'firstname'),

	'clientOptions'=> array(

		'validateOnSubmit'=>true,

		'afterValidate'=>'js:afterValidate'

	),

)); ?>


....




And in my controller:




public function actionCheckDuplicate() {

		$model=new ClubMembers;


		if(isset($_GET['ClubMembers'])) {

			$model->attributes=$_GET['ClubMembers'];


			$result = ClubMembers::model()->exists('firstname = :firstname AND surname = :surname',

				array( ':firstname'=>$model->firstname, ':surname'=>$model->surname )

			);

			

			if( $result )

				$this->renderPartial('possibleDuplicate', array('model'=>$model));

		}

	}




(Joe) #3

Adhoc: I would use a valdiation rule in combination of a flag (Yii::app()->user->hasState( …) or a hidden field in the form) if the user has confirmed to save similar record.

Write your own validator: see Create your own Validation Rule




public function rules()

	{

		return array(

				...

				 array('Firstname,Surname', 'checkDuplicate'),

				...

		    );

	}




public function checkDuplicate($attribute) 

{

   if(!$this->checkSimilar() && !Yii::app()->user->getState('confirmedSimilar'))

     $this->addError($attribute,' .... similar found ... maybe render a confirm message here'); 

}




protected function checkSimilar() 

{

   $firstName = $this->firstName;

   $surName = $this->surName;


   .... you db checks here ....


}




In your controller you have to check the confirmation, otherwise display the model again with the errormessage.

But this is only an idea, needs more investigation and work.


(Rossmccaughrain) #4

Thanks for the input Joblo. It definately put me on the right path. Heres my solution to date (with the extension attached in case it helps anyone else out!)

So just to re iterate what the issue was. I wanted to validate a form based on 1 or more fields to see if there already exists a value in the database which matches (not primary key columns but things like Firstname+Surname where is perfectly valid that a person has the same name but you want to make sure they arent adding a person because they think they dont already exist in the DB)

So heres what ive done:

Created a new extension called checkDuplicate which contains:

  • CheckDuplicateValidator - Takes multiple model attributes and adds an error to the form if they all already exist

  • EnableDuplicateAction - Sets User state to allow for addition of a duplicate value

  • DisableDuplicateAction - Sets User state to not allow addition of a duplicate value

  • ResetDuplicateBehavior - Resets User state to not allow addition of a duplicate value after afterSave() is called

Put the files in protected/extensions/checkDuplicate

In my main.php config file added (more for ease than requirement as imnot 100% sure of importing in Yii etc)




'import'=>array(

	....,

	'ext.checkDuplicate.*'

),



Then in my controller (to enable the actions):




public function actions() {

	return array(

		'enableduplicate' => 'ext.checkDuplicate.EnableDuplicateAction',

		'disableduplicate' => 'ext.checkDuplicate.EnableDuplicateAction',

	);

}



Then in my Model:




// Add the validation (ideally a better way to get the message 

// would be good (perhaps renderpartial but not sure if this is best suited in the model)

public function rules()

{

	return array(

		....,

		array('firstname, surname', 'ext.checkDuplicate.CheckDuplicateValidator', 

		'message'=>'<div id="duplicateExists">A member already exists with the name: <b>{firstname} {surname}</b><br/>

		<p>Do you wish to continue adding this user?</p>

		<p>'.CHtml::ajaxLink('Yes', 'enableDuplicate', 

		array('success'=>'js:function(data) { $("#duplicateExists").html(data); }')).'</p></div>'

		),

		.....

	);

}


// Behaviour to reset the allow duplicate user state after they have saved the value

// possibly should add additional behaviour to rest if they decide not to save the model

public function behaviors() {

	return array(

		'checkDuplicate' => array(

			'class' => 'ext.checkDuplicate.ResetDuplicateBehavior',

		),

	);

}



Anyone hope this helps someone. Feel free to suggest improvements/flaws etc as id love to hear any feedback on this.

Thanks again

Ross


(Info) #5

I have try to use it but i don’t go, I don’t recive any message from form, how I have to put it into my view? I have to enable ajax validation?

If someone can help me thanks.


(mogoch) #6

This is just what I need. Where can one find the attachment?


(Rossmccaughrain) #7

Lol I’ve no memory of writing this post! I’ll check later to see if I still have the attachment. Thanks


(Rossmccaughrain) #8

checkDuplicate.zip