I have model with rules
public function rules() {
return array(
array('user_id, name, start_date, timezones, start_hours, return_date, return_hours, location_start, location_end, trip_activity, trip_mean, status', 'required'),
array('user_id, return_hours, sign_off, saved, advise, time_notification, status', 'numerical', 'integerOnly'=>true),
array('name, going_with, start_hours, location_start, location_end, location_return, trip_activity, trip_mean', 'length', 'max'=>255),
array('created, modified, advise, notify_best_friend, notify_now, notify_returning, send_notification, sign_off', 'safe'),
array('going_with, location_return, time_notification, created, modified', 'default', 'setOnEmpty' => true, 'value' => null),
array('id, user_id, name, going_with, start_date, start_hours, return_date, return_hours, location_start, location_end, location_return, trip_activity, trip_mean, saved, advise, time_notification, status, created, modified', 'safe', 'on'=>'search'),
array(
'return_date',
'compare',
'compareAttribute'=>'start_date',
'operator'=>'>=',
'allowEmpty'=>false ,
'message'=>'{attribute} must be greater than "{compareValue}".'
),
array(
'return_hours',
'compare',
'compareAttribute'=>'start_hours',
'operator'=>'>',
'allowEmpty'=>false ,
'message'=>'{attribute} must be greater than "{compareValue}".'
),
);
}
I want to compare date and time...
In case: 'return_date' >= 'start_date'... it's ok.
In case 'return_date' == 'start_date', so 'return_hours > 'start_hours' but with rules above I can't compare them.
What's solution? thanks!
You can achieve this using a custom validator.
public function comparedates($attribute,$params)
{
$message=Yii::t('yii','{attribute} must be greater than "{compareValue}".');
if(CDateTimeParser::parse($this->return_date, "yyyy-MM-dd") < CDateTimeParser::parse($this->start_date, "yyyy-MM-dd"))
{
$params=array('{attribute}'=>$this->getAttributeLabel('return_date'),'{compareValue}'=>$this->getAttributeLabel('start_date'));
$this->addError($attribute,strtr($message,$params));
}
else if(CDateTimeParser::parse($this->return_date, "yyyy-MM-dd") === CDateTimeParser::parse($this->start_date, "yyyy-MM-dd"))
{
if(CDateTimeParser::parse($this->return_hours, "hh") < CDateTimeParser::parse($this->start_hours, "hh")//change hh according to the format of return_hours and start_hours
{
$params=array('{attribute}'=>$this->getAttributeLabel('return_hours'),'{compareValue}'=>$this->getAttributeLabel('start_hours'));
$this->addError('return_hours',strtr($message,$params));
}
}
}
And in your rules
public function rules() {
return array(
//your previous rules
array('return_date','comparedates'),
);
}
Remember change the the patternparameter of CDateTimeParser::parse() from hh according to the format of your return_hours and start_hours
Related
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()
),
...
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()
),
...
im here again with a new problem. I am trying to upload a file using yii upload function.
Everything saves well, exept for the image. Here's my code:
Controller:
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$dir = Yii::getPathOfAlias('webroot.images.producten');
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Producten']))
{
$model->attributes=$_POST['Producten'];
$model->images=CUploadedFile::getInstance($model,'images');
$nf = $model->images;
if($model->save()){
$this->redirect(array('view','id'=>$model->id));
$model->images->saveAs($dir.'/'.$nf);
$model->images = $nf;
$model->save();
}
}
$this->render('update',array(
'model'=>$model,
));
}
Form:
<div class="row">
<?php echo $form->labelEx($model,'images'); ?>
<?php echo CHtml::activeFileField($model,'images'); ?>
<?php echo $form->error($model,'images'); ?>
</div>
Model:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('naam, beschrijving, prijs', 'required'),
array('images,', 'file', 'allowEmpty'=>true,
'safe' => true,
'types'=> 'jpg, jpeg, png, gif',
'maxSize' => (1024 * 300), // 300 Kb
),
array('aangepast_door', 'numerical', 'integerOnly'=>true),
array('naam', 'length', 'max'=>50),
array('prijs, actieprijs', 'length', 'max'=>10),
//array('toegevoegd, aangepast', 'safe'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('naam, beschrijving, prijs, actieprijs', 'safe', 'on'=>'search'),
);
}
Please help me get this to work.
First of all add enctype= "multipart/form-data" to your form tag or add "enctype" option to associative array if you used form widget yo begin form.
If it will not helps you, please post var_dump($_POST) results here
I've looking but can't get It to work.
These are my rules in model Acta.php
public function rules()
{
return array(
array('dominio', 'required'),
array('numero, velocidad, grupo, dni, cuit, plan_pago_id', 'numerical', 'integerOnly'=>true),
array('foto, observaciones, situacion, infractor, dominio, tipo_vehiculo, marca, modelo, domicilio, codigo_postal, localidad, provincia, tipo_multa, usuario', 'length', 'max'=>255),
array('hora', 'length', 'max'=>11),
//Here is the problem with only this three attributes
array('municipio, cinemometro, fecha_labrada', 'safe', 'on'=> 'create,update'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, numero, fecha_labrada, velocidad, grupo, foto, observaciones, situacion, infractor, dominio, dni, cuit, tipo_vehiculo, marca, modelo, domicilio, codigo_postal, localidad, provincia, tipo_multa, hora, usuario, plan_pago_id', 'safe', 'on'=>'search'),
);
}
And this is the code on controller ActaController.php
public function actionCreate()
{
$model = new Acta;
if(isset($_POST['Acta']))
{
...
code setting data on $_POST['Acta']
...
$model->attributes = $_POST['Acta'];
$model->save();
}
$this->redirect(array('ingresar'));
}
I can't see the problem. Should be working right?
EDIT:
I thought that the scenario was set automatically. I was wrong.
To fix this the scenario must be set before the attributes:
...
$model->setScenario('create');
$model->attributes = $_POST['Acta'];
...
Before you save, You absolutely have some errors. To be aware about errors do like below:
if($model->validate()){
//NO ERRORS, SO WE PERFORM SAVE PROCESS
$model->save()
}else{
//TO SEE WHAT ERROR YOU HAVE
CVarDumper::dump($model->getErrors(),56789,true);
Yii::app()->end();
//an alternative way is to show attribute errors in view
}
On the other hand, it seems you set some attributes as safe on specific scenarios. But you did not set the scenario.
to set scenario, do like below:
$model->setScenario('THE SCENARIO NAME');
Or:
$model=new YOURMODELNAME('SCENARIO NAME');
I hope it help
I am working in Yii and I am just a beginner and trying my best to learn the framework and here is where I am stuck at :
I have created a user model and the required forms that go with it, and I am trying to implement the Captcha for it :
This is my validation rules in the user model :
$public verifyCode
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('username, password, email', 'required'),
array('username','unique'),
array('email','email'),
array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()),
array('username, password', 'length', 'max'=>45),
array('email', 'length', 'max'=>100),
array('active', 'length', 'max'=>1),
array('created_on, updated_on', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, username, password, email, created_on, updated_on, active', 'safe', 'on'=>'search'),
);
}
And this is my overriden action() in my userController :
public function actions(){
return array(
'captcha'=>array(
'class' => 'CCaptchaAction',
)
);
}
And this is my view file :
<?php if(CCaptcha::checkRequirements()): ?>
<div class="row">
<?php echo $form->labelEx($model,'verifyCode'); ?>
<div>
<?php $this->widget('CCaptcha'); ?>
<?php echo $form->textField($model,'verifyCode'); ?>
</div>
<div class="hint">Please enter the letters as they are shown in the image above.
<br/>Letters are not case-sensitive.</div>
<?php echo $form->error($model,'verifyCode'); ?>
</div>
<?php endif; ?>
According to me, I think that I am doing everything correctly however, the captcha image is not getting generated. Oh and yes the GD library is installed and if I navigate to the site/contact, there the captcha is generated fine.
I dont seem to understand, where am i getting it wrong.
This is the thing that I see :
The forms seems to be working fine however, I cant see the the captcha image.
Any help would be appreciated.
Regards,
I got the answer, it is because of the access rules that are defined in the controller, I had to modify the controller accessControl like so :
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view','captcha'),
'users'=>array('*'),
),
array('allow', // allow authenticated user to perform every action
'actions'=>array('create','update','admin','delete'),
'users'=>array('#'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}