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