iDams
(Dams92)
August 26, 2012, 3:55pm
1
Hi,
Here is my problem, I have a brand table and a realisation table. Each brand has many realisations. I’ve succeed to make the unique validator for brands like this:
array('name', 'unique', 'className' => 'Brand', 'attributeName' => 'name', 'message' => 'Name already exist'),
But I don’t know for realisations. I’d like that the name of a realisation is unique in a brand. Like you can have
Nike (brand) with shoes and clothes (realisations)
Reebok (brand) with shoes and shorts (realisations)
So I want the unique validator check in a specific brand not in all realisations!
Do you have any idea?
I’ve already tried that but it doesn’t work:
array('name', 'unique', 'criteria'=>array(
'condition'=>'"secondKey"=:secondKey',
'params'=>array(
':secondKey'=>$this->brand_id
)
)),
Thanks!
chennaiiq
(Chennaiiq)
August 26, 2012, 4:03pm
2
seenivasan
(Chellamnivas)
August 26, 2012, 5:17pm
3
Dear friend,
Can you please try this in your Realization Model.
array('name', 'checkMyUniqunessInBrand')
public function checkMyUniqunessInBrand($attribute,$params)
{
if(Realisation:model()->count('name=:name AND brand_id=:brand_id',
array(':name'=>$this->name,':brand_id'=>$this->brand_id)) > 0)
return false;
else return true;
}
OR
array('name', 'unique', 'criteria'=>array(
'condition'=>'name=:name AND brand_id=:brand_id',
'params'=>array(':name'=>$this->name,':brand_id'=>$this->brand_id)
)),
redguy
(Maciej Lizewski)
August 26, 2012, 9:57pm
4
seenivasan:
Dear friend,
Can you please try this in your Realization Model.
array('name', 'checkMyUniqunessInBrand')
public function checkMyUniqunessInBrand($attribute,$params)
{
if(Realisation:model()->count('name=:name AND brand_id=:brand_id',
array(':name'=>$this->name,':brand_id'=>$this->brand_id)) > 0)
return false;
else return true;
}
This won’t work because custom function validators are not supposed to return any value. Instead they should just set errors:
array('name', 'checkMyUniqunessInBrand')
public function checkMyUniqunessInBrand($attribute,$params) {
if(Realisation:model()->count('name=:name AND brand_id=:brand_id',
array(':name'=>$this->name,':brand_id'=>$this->brand_id)) > 0) {
$this->addError( $attribute, "$attribute must be unique in brand scope!" );
}
}
iDams
(Dams92)
August 27, 2012, 2:08pm
5
redguy:
array('name', 'checkMyUniqunessInBrand')
public function checkMyUniqunessInBrand($attribute,$params) {
if(Realisation:model()->count('name=:name AND brand_id=:brand_id',
array(':name'=>$this->name,':brand_id'=>$this->brand_id)) > 0) {
$this->addError( $attribute, "$attribute must be unique in brand scope!" );
}
}
Thanks it works!
The only problem now is for update a realization. You can’t save, it says that it must be unique. Is there a way
to check if the name changed? Such as we save the name before update and check if it has changed? Because I need this check for the
update in case the user change the realization name by a name already used.
Thank you guys for all the help!
seenivasan
(Chellamnivas)
August 27, 2012, 2:46pm
6
I really thank redguy for his inputs.
Dear iDams
Can you please try this.
array('name', 'checkMyUniqunessInBrand')
public function checkMyUniqunessInBrand($attribute,$params) {
if($this->getIsNewRecord() && Realisation:model()->count('name=:name AND brand_id=:brand_id',
array(':name'=>$this->name,':brand_id'=>$this->brand_id)) > 0) {
$this->addError( $attribute, "$attribute must be unique in brand scope!" );
}
}
iDams
(Dams92)
August 27, 2012, 2:57pm
7
seenivasan,
It works but now during the update I can put a name that already exists so it’s not good!
redguy
(Maciej Lizewski)
August 27, 2012, 3:33pm
8
iDams:
Thanks it works!
The only problem now is for update a realization. You can’t save, it says that it must be unique. Is there a way
to check if the name changed? Such as we save the name before update and check if it has changed? Because I need this check for the
update in case the user change the realization name by a name already used.
Thank you guys for all the help!
read this topic: http://www.yiiframework.com/forum/index.php/topic/34179-unique-multiple-columns-validate-with-ajaxvalidation-wont-work/page__p__164516__fromsearch__1#entry164516
I posted there snippet how to call CUniqueValidator with additional filter condition from custom function. This should do the trick.
iDams
(Dams92)
August 27, 2012, 4:01pm
9
Thank you but I don’t really understand what validate is doing. But like you said in this other topic secondKey give me the new attribute. So,
I’m almost done, I just want to know the current one before assignment. But I can’t find it. I’ve looked at $attribute and $params variables, but
it’s not. Do you know how to get this value?
With it, I could compare with the new one et know if it has changed or not.
Thanks redguy!
redguy
(Maciej Lizewski)
August 27, 2012, 5:35pm
10
to track changes in model you should use "afterFind":
class MyModel extends CActiveRecord {
private $_previousAttributeValue = null;
public function afterFind() {
parent::afterFind();
$this->_previousAttributeValue = $this->attribute;
}
public function isAttributeChanged() {
return $this->_previousAttributeValue !== null && $this->_previousAttributeValue !== $this->attribute;
}
seenivasan
(Chellamnivas)
August 27, 2012, 6:41pm
11
redguy:
to track changes in model you should use "afterFind":
class MyModel extends CActiveRecord {
private $_previousAttributeValue = null;
public function afterFind() {
parent::afterFind();
$this->_previousAttributeValue = $this->attribute;
}
public function isAttributeChanged() {
return $this->_previousAttributeValue !== null && $this->_previousAttributeValue !== $this->attribute;
}
Dear redGuy
could you please tell me the following code serves the same purpose?
public function actionSomething($id)
{
$model=$this->loadModel($id);
$oldOne=$model->someAttribute;
if(isset($_POST['Model']))
{
$model->attributes=$_POST['Model'];
$newOne=$model->someAttribute;
if($oldOne==$newOne)
{
//Do some logic...
}
}
}
Regards.
redguy
(Maciej Lizewski)
August 28, 2012, 6:54am
12
seenivasan:
Dear redGuy
could you please tell me the following code serves the same purpose?
public function actionSomething($id)
{
$model=$this->loadModel($id);
$oldOne=$model->someAttribute;
if(isset($_POST['Model']))
{
$model->attributes=$_POST['Model'];
$newOne=$model->someAttribute;
if($oldOne==$newOne)
{
//Do some logic...
}
}
}
Regards.
Yes it does pretty same. The only difference is in conceptions of fat-controller vs fat-model (meaning: where you put your business logic)
iDams
(Dams92)
August 30, 2012, 1:01pm
13
redguy:
to track changes in model you should use "afterFind":
class MyModel extends CActiveRecord {
private $_previousAttributeValue = null;
public function afterFind() {
parent::afterFind();
$this->_previousAttributeValue = $this->attribute;
}
public function isAttributeChanged() {
return $this->_previousAttributeValue !== null && $this->_previousAttributeValue !== $this->attribute;
}
Thank you redguy, it works great!