Yii 1.x - required field saves empty - php

I have a field set as required in the model, yet I have seen users saving it as an empty string (ie. ''). When I tested it, I do receive the "Cannot be blank" message properly, so don't know how to prevent this in the future. Do I have to specify all scenarios in the rule (eg, 'insert', 'update')? By the way, I tried updating the field, and it doesn't let me save it empty (I even tries spaces).
These are the rules applied on the field (model):
public function rules()
{
return array(
array('field', 'required'),
array('field', 'length', 'max'=>4096),
array('field', 'safe', 'on'=>'search'),
);
}
For #RiggsFolly :) the controller action:
public function actionUpdate($id)
{
$model = Model::model()->findByPk($id);
$formData = Yii::app()->request->getPost('Model');
if ($formData)
{
$model->attributes = $formData;
$model->save();
}
$this->render('update',array(
'model'=>$model
));
}
... and the view:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'form'
)); ?>
<?php echo $form->textArea($model,'text',array( 'rows'=>5 ')); ?>
<?php $this->endWidget(); ?>
Can you imagine any scenario this field could be saving an empty string in the database?

Related

how to make a function execute in model without calling in controller ,YII framework

In my yii based sample project I have a model named gateway and this model has a variable from DB with name $time that is a creation time for gateway
that comes from php time() function.
I want to change this variable to a readable form to show in view (not to save in DB) and for this I wrote a function setTime() and defined a variable $readabletime
I didn't call function settime() in controller but in rules() of model
I wrote this line:
array('time','setTime')
but it doesn,t work
How can I make a function work in model?
This is my model
<?php
class UserGateway extends CActiveRecord
{
public $readabletime;
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'user_gateway';
}
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('name, url, ip, time, userid, gatewaycategoryid', 'required'),
array('time, status, userid, gatewaycategoryid, defaultgateway', 'numerical', 'integerOnly'=>true),
array('name, url', 'length', 'max'=>120),
array('ip', 'length', 'max'=>18),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, name, url, ip, time, status, userid, gatewaycategoryid, defaultgateway', 'safe', 'on'=>'search'),
array('time','setTime')
);
}
public function setTime()
{
$this->readabletime=date('m/d/Y H:i:s', $this->time);
}
}
and this is my view:
<?php echo CHtml::link('Advanced Search','#',array('class'=>'search- button')); ?>
<div class="search-form" style="display:none">
</div><!-- search-form -->
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'UserAccountnumber-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'name',
'url',
'ip',
'readabletime',
array(
'class'=>'CButtonColumn',
'buttons'=>array(
'update' => array(
'url'=>'Yii::app()->createUrl(\'User/UpdateGateway\',array(\'id\'=>$data[id]))'),
'delete' => array(
'url'=>'Yii::app()->createUrl(\'User/DeleteGateway\',array(\'id\'=>$data[id]))'
), ),
)
)
)
);
?>
thank you all for answering
You could just write afterFind function in your model:
protected function afterFind()
{
// convert to readable time format while viewing
$this->readabletime = date('m/d/Y H:i:s', $this->time);
parent::afterFind();
}
This way wherever readabletime is used, it will convert it to your desired format. CActiveRecord afterFind
1) Validation rules and their functions are only called on $model->validate().
2) You've just hijacked Yii's native method for setting database properties without calling the parent, meaning your setTime() function will be called when something like this is done: $model->time = time(); meaning time will never get set on the internal array of database attributes; meaning a time value will never be saved in the database. Conclusion: don't do that.
3) There are a couple ways you can accomplish this.
i. Override the afterFind() (http://www.yiiframework.com/doc/api/1.1/CActiveRecord#afterFind-detail) function, and set $readdabletime equal to a formatted version of time. This will be called right after your model properties are loaded from the database (make sure to call parent::afterFind() at the bottom of your function.
ii. Remove the line, public $readdabletime;, and add this function to your code instead:
public function getReaddabletime() {
return date('m/d/Y H:i:s', $this->time);
}
The formatted time will be accessible like this: $model->readdabletime
In your model simply do
public function getTime(){
return date('m/d/Y H:i:s', $this->time);
}
Then, in CGridView
'url',
'ip',
array(
'name' => 'Readable time',
'value' => $model->getTime()
),
...

how to make a function work in a model class in yii framework [duplicate]

In my yii based sample project I have a model named gateway and this model has a variable from DB with name $time that is a creation time for gateway
that comes from php time() function.
I want to change this variable to a readable form to show in view (not to save in DB) and for this I wrote a function setTime() and defined a variable $readabletime
I didn't call function settime() in controller but in rules() of model
I wrote this line:
array('time','setTime')
but it doesn,t work
How can I make a function work in model?
This is my model
<?php
class UserGateway extends CActiveRecord
{
public $readabletime;
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'user_gateway';
}
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('name, url, ip, time, userid, gatewaycategoryid', 'required'),
array('time, status, userid, gatewaycategoryid, defaultgateway', 'numerical', 'integerOnly'=>true),
array('name, url', 'length', 'max'=>120),
array('ip', 'length', 'max'=>18),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, name, url, ip, time, status, userid, gatewaycategoryid, defaultgateway', 'safe', 'on'=>'search'),
array('time','setTime')
);
}
public function setTime()
{
$this->readabletime=date('m/d/Y H:i:s', $this->time);
}
}
and this is my view:
<?php echo CHtml::link('Advanced Search','#',array('class'=>'search- button')); ?>
<div class="search-form" style="display:none">
</div><!-- search-form -->
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'UserAccountnumber-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'name',
'url',
'ip',
'readabletime',
array(
'class'=>'CButtonColumn',
'buttons'=>array(
'update' => array(
'url'=>'Yii::app()->createUrl(\'User/UpdateGateway\',array(\'id\'=>$data[id]))'),
'delete' => array(
'url'=>'Yii::app()->createUrl(\'User/DeleteGateway\',array(\'id\'=>$data[id]))'
), ),
)
)
)
);
?>
thank you all for answering
You could just write afterFind function in your model:
protected function afterFind()
{
// convert to readable time format while viewing
$this->readabletime = date('m/d/Y H:i:s', $this->time);
parent::afterFind();
}
This way wherever readabletime is used, it will convert it to your desired format. CActiveRecord afterFind
1) Validation rules and their functions are only called on $model->validate().
2) You've just hijacked Yii's native method for setting database properties without calling the parent, meaning your setTime() function will be called when something like this is done: $model->time = time(); meaning time will never get set on the internal array of database attributes; meaning a time value will never be saved in the database. Conclusion: don't do that.
3) There are a couple ways you can accomplish this.
i. Override the afterFind() (http://www.yiiframework.com/doc/api/1.1/CActiveRecord#afterFind-detail) function, and set $readdabletime equal to a formatted version of time. This will be called right after your model properties are loaded from the database (make sure to call parent::afterFind() at the bottom of your function.
ii. Remove the line, public $readdabletime;, and add this function to your code instead:
public function getReaddabletime() {
return date('m/d/Y H:i:s', $this->time);
}
The formatted time will be accessible like this: $model->readdabletime
In your model simply do
public function getTime(){
return date('m/d/Y H:i:s', $this->time);
}
Then, in CGridView
'url',
'ip',
array(
'name' => 'Readable time',
'value' => $model->getTime()
),
...

Yii Ajax form validate only for one field

I have an email field in my model registration form and other fields like name, country, age.
and I have to do an ajax validation onChange event only for email field .
I was set my view to enable ajax validation.
my problem is the ajax validation applied for all field not only for email, I need to do this action only for one field onChange event.
this my view
$form=$this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'Login-Form',
'enableClientValidation'=>true,
'enableAjaxValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
));
echo $form->errorSummary($loginForm);
echo $form->textFieldRow($loginForm, 'email');
echo $form->textFieldRow($loginForm, 'name');
echo $form->textFieldRow($loginForm, 'age');
echo $form->textFieldRow($loginForm, 'country');
and this is my model
public function rules()
{
return array(
array('email, country, name', 'required'),
array('email', 'checkEmail')
);
}
// custom function to check email
public function checkEmail($attribute, $params)
{
$this->addError($attribute,strtr('email exsit before',$params));
}
how can enable ajax validation only for email and the other filed (country, name, age) on client side without ajax validation.
Please help I send a lot of time to do that.
Thanks
Set the form clientOption on change like this:
$form=$this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'Login-Form',
'enableClientValidation'=>true,
'enableAjaxValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>true,
So that on change it can trigger the validation
This can be done by setting the 4th parameter to false on validate trigger.
<?php echo $form->error($model,'email', array(), false); ?>
In your model set this
public function rules()
{
return array(
array('email, country, name', 'required'),
array('email', 'unique'), //check if email already exist
array('email', 'email'),
);
}
in your controller
<?php
class SiteController extends CController {
.... // Other functions
public function actionLogin(){ // Your corresponding action
$model= new LoginForm(); // Your actual model name
$_POST['ajax'] === 'Login-form' make sure that login form is the same as your form name in view
if (isset($_POST['ajax']) && $_POST['ajax'] === 'Login-form') {
echo CActiveForm::validate($model,);
Yii::app()->end();
}
... // Remaining action logic
in your view
$form=$this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'Login-Form',
'enableClientValidation'=>false,
'enableAjaxValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>false,
'validateOnChange'=>false,
'validateOnType' => true,
To perform validation via ajax you first need to call a helper function in your controller in addition to you enabling the enableAjaxValidation in your form view
In your Controller ( I am assuming the SiteController since this a login form )
<?php
class SiteController extends CController {
.... // Other functions
public function actionLogin(){ // Your corresponding action
$model= new LoginForm(); // Your actual model name
if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
echo CActiveForm::validate($model,array('email'));
Yii::app()->end();
}
... // Remaining action logic
see Validate and enableAjaxValidation api docs for full details how this works

Yii - getActiveFormWidget() returns wrong type in core?

I am only trying to create a non-AJAX registration form.
When I submit through a CForm, PHP says error() is being called on a non-object. I checked the source file where the error occurred and (using var_dump(get_class($parent->getActiveFormWidget()));) found that getActiveFormWidget() returns a CFormInputElement, which does not have error() defined.
I thought this had to do with CForm::activeForm, but it defaulted to CActiveForm.
I did try 'enableAjaxValidation'=>false.
What am I not understanding? I suspect I misinterpreted something along the way.
CFormInputElement::renderError():
public function renderError()
{
$parent=$this->getParent();
// $parent->getActiveFormWidget() returns object that does not define error()
return $parent->getActiveFormWidget()->error($parent->getModel(), $this->name, $this->errorOptions, $this->enableAjaxValidation, $this->enableClientValidation);
}
Model:
class RegisterFormModel extends CFormModel {
public $email;
public $password;
public $password_confirm;
public function rules()
{
return array(
array('email, password, password_confirm', 'required'),
array('password','compare','compareAttribute'=>'password_confirm'),
array('password, password_confirm','length','min'=>'6','max'=>'20'),
array('email', 'email'),
array('email', 'length', 'max'=>256)
);
}
public function attributeLabels()
{
return array(
'email'=>'Email',
'password'=>'Password',
'password_confirm'=>'Confirm Password',
);
}
}
View:
<div class="form">
<?php echo $form; ?>
</div><!-- form -->
Controller Action:
class RegisterAction extends CAction
{
public function run()
{
$register_model = new RegisterFormModel;
$controller = $this->getController();
$form = new CForm(array(
'title'=>'Register',
'enableAjaxValidation'=>false,
'elements'=>array(
'email'=>array(
'type'=>'text',
'maxlength'=>256,
),
'password'=>array(
'type'=>'password',
'minlength'=>6,
'maxlength'=>32,
),
'password_confirm'=>array(
'type'=>'password',
'minlength'=>6,
'maxlength'=>32,
),
),
'buttons'=>array(
'register'=>array(
'type'=>'submit',
'label'=>'Register',
),
),
), $register_model);
if($form->submitted('register', true) && $form->validate())
{
// ...
}
else
{
$controller->render('register', array('model'=>$register_model, 'form'=>$form));
}
}
}
Well, I have never seen using CForm as you show us.
I recommend you to use the active form widget,
http://www.yiiframework.com/wiki/195/implementing-a-registration-process-using-the-yii-user-management-module/
and you need to define all those fields in your CFormModel. This way you will be able to provide proper validation for them.
I know that the answer is really late :)
But for the sake of anyone else who may have a similar error.
<?php
// change from: echo $form;
echo $form->render();
?>
I was rendering the elements separately so this is how I did it:
<?php
// without the renderBegin() and renderEnd() it may give the no object error
echo $form->renderBegin();
echo $form->renderElements();
echo $form->renderEnd();
?>

kohana form validation

There is a 'main.php' view that contains a form with email and name fields and a submit button. Eveyrthing works fine with action_index (the code is below), but I'm curious how to modify the code below so it validates if the email was entered correctly. It should not put values in the database if the email field is not valid. I hope it is possible to made using ->rule. Is it? If yes, then how where to add the validation? (I had no luck trying it in different ways).
public function action_index()
{
if ( !empty($_POST) ) {
$model = ORM::factory('tbl1'); // create
$model->values($_POST); // load values to model
if ($model->check()) {
$model->save(); // save the model
} else {
//show errors
}
}
$this->response->body(View::factory('main'));
}
Thank you.
Use rules function in your ORM model:
public function rules()
{
return array(
'email' => array(
array('email', array(':value')),
),
);
}

Categories