$model-save() throwing foreach invalid argument error in Yii - php

here is my code, when i am calling this method an error occured and say "Invalid argument supplied for foreach() ". Anyone? any idea ?
$state = array(
'state_status_id' => '4',
'fax_format_preference_id' => '2',
'state_reference_code' => $state_ref->reference_code,
'leap_fqdn' => $leap_fqdn ,
'description' => $state_ref->name."--".$leap_fqdn,
);
$model = new States;
$model->setAttributes($state, false);
$model->setIsNewRecord(true);
$res = $model->save();
here is stack info:
public function createValidators(){
$validators=new CList;
foreach($this->rules() as $rule)
{
if(isset($rule[0],$rule[1])) // attributes, validator name
$validators->add(CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2)));
else
throw new CException(Yii::t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.',
array('{class}'=>get_class($this))));
}
return $validators;
}
this is Rule method, i don't know why this is not working while same things is working fine in other models and controllers.
public function rules()
{
//Rules for admins editing state information
if(Roles::has_permission('update','all_states'))
{
return array(
array('state_status_id, fax_format_preference_id, state_reference_code, leap_fqdn, description', 'required'),
array('state_status_id, fax_format_preference_id', 'length', 'max'=>10),
array('leap_fqdn', 'length', 'max'=>128),
array('description', 'length', 'max'=>255),
array('updated_at,default_user_role', 'safe'),
// Please remove those attributes that should not be searched.
array(' state_status_id, fax_format_preference_id, created_at, updated_at, state_reference_code, leap_fqdn, description', 'safe', 'on'=>'search'),
);
}
if(Roles::has_permission('update','state_state'))
{
return array(
array('fax_format_preference_id', 'required'),
array('fax_format_preference_id', 'length', 'max'=>10),
array('updated_at', 'safe'),
);
}
}

Apparently in your case (which causes the error) both condition checks are false, hence rules-method returns nothing.
Try to add return array(); to the rules method, it will be sort of fallback in case both checks fail.
public function rules()
{
// your current code
return array(); //fallback
}

Related

Yii: How change unique criteria?

public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('entity_category_id, entity_id', 'required'),
array('preferred','boolean'),
// unique with condition
array('email','unique',
'criteria'=>array(
'condition' => 'gmail= :gmail OR email= :email',
'params' => array(':email' => $this->email, ':gmail' => $this->email)
),
),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, entity_category_id, entity_id', 'safe', 'on'=>'search'),
);
}
Above unique query run WHERE clause as (gmail = 'abc' OR email= 'abc') AND (email = 'abc)
but I don't want and condition, i want only (gmail = 'abc' OR email= 'abc') in where clause
It's normal that criteria is added to the original condition. From the Yii API:
criteria: additional query criteria. Either an array or CDbCriteria. This will be combined with the condition that checks if the attribute value exists in the corresponding table column
I think the easiest way to resolve your problem is to create your own validator in your model class:
public function EmailValidator($attribute,$params)
{
$criteria = new CDbCriteria;
$criteria->condition = 'gmail= :gmail OR email= :email';
$criteria->params = array(':email' => $this->email, ':gmail' => $this->email);
$result = $this->findAll($criteria);
if(!empty($result)) {
$this->addError($attribute, 'Email already exists!');
}
return;
}
And call it in your rules method:
public function rules()
{
return array(
//Other rules
array('email', 'EmailValidator'),
);
}

Save model instance doesn't work in Yii

I have these codes but save() method doesn't work. What is the problem?
public function rules()
{
return array(
array('name', 'required'),
array('name site_id', 'unique'),
array('status, site_id', 'numerical', 'integerOnly'=>true),
array('name, author', 'length', 'max'=>50),
array('version', 'length', 'max'=>10),
array('config_content', 'safe'),
array('id, name, author, version, status, config_content, site_id', 'safe', 'on'=>'search'),
);
}
and
$new_row = new Module;
$new_row->name = 'test';
$new_row->config_content = 'asasfdfd';
$new_row->site_id = 2;
$new_row->status = 0;
if($new_row->save())
echo 'Yes!';
else
echo 'No!';
Hi from what I can see the most likely cause will be because there is a "," missing in the following rule
array('name site_id', 'unique'),
should be
array('name, site_id', 'unique'),

Validation Rules are not working for change password in Yii php?

I am creating change password functionality, all things are working fine except the old password validation rule.here is my code
public function rules()
{
return array(
array('is_active', 'numerical', 'integerOnly'=>true),
array('first_name, joining_date,last_name, employee_code, username, password, role', 'required','on'=>array('create')),
array('employee_code', 'numerical', 'integerOnly'=>true),
array('username','email'),
array('username','valid_username','on'=>array('create')),
//array('username', 'contraints', 'readOnly'=>true, 'on'=>'update'),
array('currentPassword, newPassword, newPasswordRepeat', 'required','on'=>array('change')),
//array('newPassword', 'length', 'min' => 6, 'max'=>20, 'message'=>Yii::t("translation", "{attribute} is too short.")),
//array('newPassword','ext.SPasswordValidator.SPasswordValidator', 'preset' => 'strong', 'max' => 41),
array('newPassword', 'compare', 'compareAttribute'=>'newPasswordRepeat','on'=>array('change')),
array('currentPassword', 'equalPasswords','on'=>array('change')),
array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements(),'on'=>array('forgotPassword')),
array('joining_date', 'safe'),
array('user_id, first_name, last_name, employee_code, username, password, role, joining_date, pending_regular_leave, pending_medical_leave, allocated_regular_leave, allocated_medical_leave, is_active', 'safe', 'on'=>'search'),
);
}
My change password function is
public function equalPasswords($attribute, $params)
{
$user = Users::model()->findByPk(Yii::app()->user->id);
if ($user->password != md5($attribute))
{
$this->addError($attribute, 'Old password is incorrect.');
}
}
Update method
:
public function actionChange()
{
$model=new Users;
$model->setScenario('change');
if (isset($_POST['Users'])) {
$model->setAttributes($_POST['Users']);
if($model->validate())
{
$pass = md5($_POST['Users']['newPassword']);
$userModel = Users::model()->findByPk(Yii::app()->user->id);
$userModel->password = $pass;
$data = $userModel->update();
Yii::app()->user->setFlash('success',"Password changed successfully!");
}
}
$this->render('change_password', array('model'=>$model,true));
}
when i try to change password with all the correct parameters (correct old password,new password,retype password) it update the password but also shows me error that your old password does not correct .please help me to resolve this as i am new to Yii.
Thanks in advanced.
I'm not sure but you can try once.
$user = Users::model()->findByPk(Yii::app()->user->id);
if ($user->password != md5($this->attributes['currentPassword']))
{
$this->addError($attribute, 'Old password is incorrect.');
}
change md5($attribute) to md5($this->attributes['currentPassword']
And add this in your rules
public function rules()
{
public $currentPassword;
// your rules here
}
In the validator you receive the attribute name, not the value in $attribute. To get the value you'd have to:
$value = $this->$attribute;

Yii validation of a specific field

problem defenition
i have one model called 'user.php'
i have some validation rules on the same as follows
i am now going to create a password reset form
in that form i have a text box name email (same email used in user model)
in password reset form i would like to check wheather this user is a registered one if it a registered one will send the password reset link
I DONT KNOW HOW TO VAIDATE THIS EMAIL FIELD , ANY HELP HIGHLY APPRECIABLE AS I AM NEW IN YII
user.php
class Users extends CActiveRecord
{
public $cpassword;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return 'users';
}
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('email, password, user_type , cpassword','required'),
array('email', 'length', 'max'=>200),
array('email', 'unique'),
array('email', 'email'),
array('password', 'length', 'max'=>300),
array('cpassword', 'length', 'max'=>300),
array('user_type', 'length', 'max'=>5),
array('cpassword', 'compare', 'compareAttribute' => 'password'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, email, password, user_type ', 'safe', 'on'=>'search'),
);
}
public function relations()
{
return array(
);
}
public function attributeLabels()
{
return array(
'id' => 'ID',
'email' => 'Email',
'password' => 'Password',
'user_type' => 'User Type',
'cpassword' => 'Confirm Password'
);
}
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('email',$this->email,true);
$criteria->compare('password',$this->password,true);
$criteria->compare('user_type',$this->user_type,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
public function beforesave()
{
$this->password=md5($this->password);
return true;
}
}
You can check on the submit with something like:
$user = User::model()->find("email = '".trim($model->email)."'");
if (!empty($user)){
// users exists
} else {
// user does not exist
}
If you really want to use the model, you can setup a rule where email must be unique like so:
array('email', 'unique', 'message' => 'Email already in use'),
You can then check if the model validates on the submit, specifically the email field. If it doesnt validate the email address exists
Last, you can validate a single model attribute like so:
if($model->validate(array('attribute_name'))
// valid
}
Here is one way of doing the complete action (not the best way but the easiest to understand!)
public function actionResetpassword(){
$model = new User;
if(isset($_POST['User'])){
$model->attributes = $_POST['User']; // this is the form as completed by the user
$user = User::model()->find("email = '".trim($model->email)."'");
if (!empty($user)){
// send user their new email
$this->render("passwordreset"); // user exists, render confirmtion page
} else {
// user does not exist, render form and pass $error_message variable with messasge
$this->render("resetpassword",array(
"model" => $model,
"error_message" => "No such user found!",
));
}
} else {
// this will be rendered if the user has not submitted the form yet
$this->render("resetpassword",array(
"model" => $model,
));
}
}
public function rules() {
$action = Yii::app()->controller->action->id;
if($action == 'login'){
return array(array('username,password', 'required'), array('password', 'length', 'min'=>6, 'max'=>12), array('rememberMe', 'boolean'), array('password', 'authenticate'), array('id, jsid, email, username, password, status', 'safe', 'on'=>'search'));
}else{
return array( array('oldpassword,password1,password2', 'required'), array('password1,password2, oldpassword', 'length', 'min'=>6, 'max'=>12),array('password1', 'compare', 'compareAttribute'=>'password2'), array('id, jsid, email, username, password, status', 'safe', 'on'=>'search'),);
}
}

Yii custom validation rule not called on validate()

When a user registers for my application the following validation rules are called before submission:
public function rules()
{
return array(
array('email, firstName, lastName, password, passwordConfirm, telephone', 'required'),
array('club, email, firstName, lastName, level, password, telephone', 'length', 'max'=>45),
array('passwordConfirm', 'compare', 'compareAttribute'=>'password', 'on'=>'register'),
array('email', 'isUniqueEmailAddress'),
);
}
The first three validation rules complete successfully, but the fourth (a custom validation method) does not. It should call the function 'isUniqueEmailAddress' and perform the following:
/*
* Returns true if there doesn't exist a user in the database with the submitted email
*/
public function isUniqueEmailAddress($attribute, $params)
{
//if (User::model()->find('email=:email', array(':email'=>$this->email)) !== null)
//{
$this->addError('email', 'Email account already exists');
//}
}
As you can see, I've even commented out all logic to simply ensure that a validation error is sent back to the registration form, but no errors are returned on validation(). I've read Yii's Documentation and scoured the forums but cannot understand why my custom validation method is not being called?
I ran into this problem when attempting to set a flash message in a controller after calling $model->save(). It was a code formatting issue which caused a logic error.
For example, in the model I had something like this:
public function validateNumItems($attribute, $params) {
$this->addError($attribute, 'Validate Items Failed');
}
In theory this should have caused the form submission to fail every time for debugging purposes. But it never did.
My controller's update action looked like this:
public function actionUpdate($id) {
$model = $this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['Collection']))
{
$model->attributes = $_POST['Collection'];
if ($model->save())
Yii::app()->user->setFlash('success', "Data saved!");
$this->redirect(array('index'));
}
$this->render('update', array('model' => $model, ));
}
The missing brackets around the $model->save() test created by Gii caused a logic error when I added new lines. Putting the brackets in place fixed things.
public function actionUpdate($id) {
$model = $this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['Collection'])) {
$model->attributes = $_POST['Collection'];
if ($model->save()) {
Yii::app()->user->setFlash('success', "Data saved!");
$this->redirect(array('index'));
}
}
$this->render('update', array('model' => $model, ));
}
array('email', 'exist')
like this.
public function rules()
{
return array(
array('email, firstName, lastName, password, passwordConfirm, telephone', 'required'),
array('club, email, firstName, lastName, level, password, telephone', 'length', 'max'=>45),
array('passwordConfirm', 'compare', 'compareAttribute'=>'password', 'on'=>'register'),
array('email', 'exist')
);
}
I commented with some possible reasons your code isn't working (it looks right), but in this case you can just use the Unique validator.
array('email', 'unique') will do it.
try this, it's working fine -
public function rules()
{
return array(
array('email, firstName, lastName, password, passwordConfirm, telephone', 'required'),
array('email', 'email','message'=>"The email isn't correct"),
array('email', 'uniqueEmail'),
);
}
your custom function, write into same model -
public function uniqueEmail($attribute, $params)
{
if($user = User::model()->exists('email=:email',array(':email'=>$this->email)))
$this->addError($attribute, 'Email already exists!');
}

Categories