I am working on a project. I want to save 2 models in a same form. I've tried like this:
actionCreate in QController.php
public function actionCreate()
{
$model=new Question;
$test=new Answer;
if(isset($_POST['Question']) && ($_POST['Answer']))
{
$model->attributes=$_POST['Question'];
$model->question=CUploadedFile::getInstance($model,'question');
$test->attributes=$_POST['Answer'];
$valid=$model->validate();
$valid=$test->validate() && $valid;
if($valid){
$model->save(false);
$test->save(false);
$model->question->saveAs(Yii::app()->basePath . '/../images/questions/' . $model->question.'');
$this->redirect(array('view','id'=>$model->id_question));
}
}
$this->render('create',array(
'model'=>$model,
'test'=>$test,
));
}
Then, in my Q/_form.php
<?php $form=$this->beginWidget('bootstrap.widgets.TbActiveForm',array(
'id'=>'question-form',
'enableAjaxValidation'=>false,
)); ?>
<?php $answerModel = new Answer; ?>
<p class="help-block">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model, $answerModel); ?>
<?php echo $form->fileFieldRow($model,'question',array('class'=>'span5','maxlength'=>50)); ?>
<?php echo $form->textFieldRow($answerModel,'optionA',array('class'=>'span5','maxlength'=>100)); ?>
//rest of codes
<?php $this->endWidget(); ?>
I've tried this but still not save the data. How can I do to fix it? Thanks for your answer
You should validate first and then save data:
$model->attributes=$_POST['Question'];
$test->attributes=$_POST['Answer'];
$valid = $model->validate();
$valid = $location->validate() && $valid;
if ($valid) {
// use false parameter to disable validation
$model->save(false);
$test->save(false);
// redirect
}
And with transactions:
$model->attributes=$_POST['Question'];
$test->attributes=$_POST['Answer'];
$valid = $model->validate();
$valid = $location->validate() && $valid;
if ($valid) {
$dbTransaction = Yii::app()->db->beginTransaction();
try {
// use false parameter to disable validation
$model->save(false);
$test->save(false);
$dbTransaction->commit();
// redirect here
} catch (Exception $e) {
$dbTransaction->rollBack();
// save/process error
}
}
Related
I have login form which, where I am implementing 2 Factor Authentication integrating twilio API.
The API is working fine and I can get the verification response for success or failure.
Now I am somehow not able to display the message "OTP verification Failed" on the form.
here is my controller code:
public function actionLogin() {
$this->layout = '#app/themes/backend/login';
$model = new LoginForm(['scenario' => 'login']);
if (Yii::$app->request->isAjax && $model->load($_POST)) {
$authy_id = Yii::$app->session->get('authy_id');
// var_dump($authy_id);exit;
Yii::$app->response->format = 'json';
// var_dump($model);exit;
if(!empty($authy_id)){
$authy_api = new AuthyApi('api-key');
$token_entered_by_user = $model->otp;
$verification = $authy_api->verifyToken($authy_id, $token_entered_by_user);
if ($verification->ok()) {
// correct token
// Yii::$app->response->format = 'json';
return \yii\bootstrap\ActiveForm::validate($model);
}else{
// Yii::$app->response->format = 'json';
$model->addError('OTP Verification Failed');
print_r('error');
Yii::$app->session->setFlash('error', "OTP verification failed!");
exit;
}
}else{
Yii::$app->response->format = 'json';
return \yii\bootstrap\ActiveForm::validate($model);
}
}
if ($model->load(Yii::$app->request->post()) && $model->login()) {
if (Yii::$app->user->identity->user_role == 'admin') {
$path = "../" . Yii::$app->user->identity->user_role;
return $this->redirect($path);
}
elseif(Yii::$app->user->identity->user_role == 'customer') {
$path = "../" . Yii::$app->user->identity->user_role .'/default/index';
return $this->redirect($path);
}
else{
$path = "../" . "site/index";
return $this->redirect($path);
...
}
}
return $this->render('login', [
'model' => $model,
]);
}
and in my view file I have tried like:
<?php pjax::begin(['id'=>'otp-error']); ?>
<?php if(Yii::$app->session->hasFlash('error')):?>
<div class="info" id="otp-error">
<?= Yii::$app->session->getFlash('error') ?>
</div>
<?php endif?>
<?php pjax::end(); ?>
what I am missing here?
Remove the exit; after setting the "OTP verification failed!" message.
You are returning to nowhere just after you set that flash message.
Remember that for the flash message to work, your code must reach your view. If you return before, or return a JSON, it will never get to your client.
Don't get this.
I have to validate basic form. Im using CI form_validation library, form validation rules are set just to "required"...if form validation fails it just need to echo validation error in login form. Im using by default <?php echo validation_errors(); ?> Helper is autoloaded. Form functionality is OK it works how it should, only problem is that framework dont display error messagges if dont fill required fields?
login_form.php - VIEW
<?php echo validation_errors(); ?>
<?php echo form_input('email' , 'email'); ?> <br>
<?php echo form_input('password' , 'password'); ?> <br>
<?php echo form_submit('submit' , 'submit'); ?>
login.php - CONTROLLER
<?php
Class Login extends CI_Controller {
function index () {
$data ['content'] = "login_form";
$this->load->view("template", $data);
}
function validate() {
$this->load->library("form_validation");
$this->form_validation->set_rules('email' , 'email' , 'trim|xss_clean|required');
$this->form_validation->set_rules('password' , 'password' , 'md5|trim|required');
if( $this->form_validation->run() == FALSE) {
redirect('login/index');
}
else {
redirect("user/profile");
}
}
}
?>
Why don't you use code in controller like this hope will help you just set form action to login.php
login.php - CONTROLLER
function index () {
$data ['content'] = "login_form";
$this->load->library("form_validation");
$this->form_validation->set_rules('email' , 'email' , 'trim|xss_clean|required');
$this->form_validation->set_rules('password' , 'password' , 'md5|trim|required');
if( $this->form_validation->run() == FALSE) {
$this->load->view("template", $data);
}
else {
redirect("user/profile");
}
}
login_form.php - VIEW
<?php echo validation_errors(); ?>
<?php echo form_input('email' , 'email'); ?> <br>
<?php echo form_input('password' , 'password'); ?> <br>
<?php echo form_submit('submit' , 'submit'); ?>
if( $this->form_validation->run() == FALSE) {
redirect('login/index');
}
Don't redirect, else error will not be available. Instead of that keep
if( $this->form_validation->run() == FALSE) {
$data ['content'] = "login_form";
$this->load->view("template", $data);
}
Check the following link for more details:
Form Validation : CodeIgniter User Guide
I am working on a registration form
When i submit the form after the entering details the registration data get stored in the database but the the page shows the following error
A PHP Error was encountered
Severity: Notice
Message: Undefined variable: dbRet
Filename: models/registration_model.php
Line Number: 47
I am not getting the prolem the same code is working good at the localhost but what is the problem at server??
This is the model Code
class Registration_model extends CI_Model {
function __construct()
{
parent::__construct();
}
function index()
{
$data['page_title'] = 'Registration';
$this->load->view('client/general/head',$data);
$this->load->view('client/general/header');
$this->load->view('registration');
$this->load->view('client/general/footer');
}
function busregister()
{
$data['page_title'] = 'Registration';
$this->load->view('business/registration1');
}
public function save_registration($un,$email,$pwd,$utype)
{
try
{
$data = array(
'username' => $un,
'password' => $pwd,
'email' => $email
);
//print_r($data);
//die();
$this->load->database();
$this->db->reconnect();
if($utype=='buss')
{
$dbRet=$this->db->insert('business', $data);
}
else
{
$dbRet-$this->db->insert('user', $data);
}
if (!$dbRet) {
$ret['ErrorMessage'] = $this->db->_error_message();
$ret['ErrorNumber'] = $this->db->_error_number();
log_message('error', "DB Error: (".$ret['ErrorNumber'].") ".$ret['ErrorMessage']);
$this->db->close();
return $ret['ErrorNumber'];
}
else{
$rid=$this->db->insert_id();
$this->db->close();
return $rid;
}
}
catch (Exception $e){
return -1;
}
}
}?>
This is the controller code
class Registration extends CI_Controller {
public function index()
{
$this->load->helper(array('registration','date','country'));
$this->load->helper('client');
$this->load->model('Registration_model');
if ($this->input->post("submit_registration",TRUE))
{
if($this->form_validation->run("stud_registration_rules"))
{
$this->load->library(array('encrypt'));
$stud_first_name = $this->input->post('stud_user_name');
$stud_email = $this->input->post('stud_email');
$stud_pass = $this->input->post('stud_password');
$retval=$this->Registration_model->save_registration($stud_first_name,$stud_email,$this->encrypt->encode($stud_pass),"user");
var_dump($this->encrypt->encode($stud_pass));
if($retval!==-1){ //SAVE SUCCESS
$this->session->set_flashdata('flashSuccess', 'Record saved successfully.');
redirect('/');
}
else{
$this->session->set_flashdata('flashError', 'Error Saving Record');
redirect('/registration');
}
}
else{
// FORM IS NOT VALIDATED
$this->session->set_flashdata('flashError', 'Validation fields error');
redirect('/registration');
}
}
$this->Registration_model->index();
}
}
This is the view code
<div class="content">
<div class="container_12">
<div class="grid_12">
<?php if($this->session->flashdata('flashSuccess')) : ?>
<div class="alert alert-success">
×
<p><?php print_r($this->session->flashdata('flashSuccess'));
?></p>
</div>
<?php endif; ?>
<?php if($this->session->flashdata('flashError')) : ?>
<div class="alert alert-danger">
×
<p><?php print_r($this->session->flashdata('flashError'));
?></p>
</div>
<?php endif; ?>
<?php echo registration_form();?>
</div>
</div>
In your Model code Registration_model , Else part assignment operator is wrong
change the following line
$dbRet-$this->db->insert('user', $data);
to
$dbRet = $this->db->insert('user', $data);
So here is what i am doing, i have created a dependent drop down in a form and i am validating it on my controller :
public function actionCreate()
{
$model=new Management;
if(isset($_POST['Management']))
{
if($_POST['Management']['company_id']==''){
//error please select a company
Yii::app()->user->setFlash('company_error',"Please select a company.");
$this->redirect(array('create'));
}else{
if($_POST['Management']['site_id']==''){
//error please select a site
Yii::app()->user->setFlash('site_error',"Please select a site.");
Yii::app()->user->setFlash('cid',$_POST['Management']['company_id']);
$this->redirect(array('create'));
}else{
//save
$model->attributes=$_POST['Management'];
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
}
}
$this->render('create',array(
'model'=>$model,'update'=>''
));
}
and i am passing the company id to my form view, and i want to keep the previous drop down selected if the validation fails. this is what my dropdown looks like :
<div class="row">
<?php echo $form->labelEx($model,'company_id'); ?>
<?php echo $form->dropDownList($model, 'company_id', $company, /*array('options'=>array($cid=>array('selected'=>true))),*/
array(
'ajax' => array(
'type'=>'POST',
'url'=>CController::createUrl('Management/dropDownSite'),
'update'=>'#SectorManagement_site_id',
'data'=>array('CompanyId'=>'js:this.value'),
)));
?>
<?php echo $form->error($model,'company_id'); ?>
</div>
Now when i uncomment the code :
array('options'=>array($cid=>array('selected'=>true))),
from the above drop down it shows the pre-selected value but then the dependent drop down does not work..any idea how should i solve this. Thanks in advance. :)
I think you are looking at this the wrong way. If your validation fails, you redirect, while you are already on the page you are redirecting too.
I am not a 100% sure but what I think you are looking for in your action is
public function actionCreate()
{
$model = new Management;
if (isset($_POST['Management'])) {
$model->attributes = $_POST['Management'];
if ($_POST['Management']['company_id'] == '') {
//error please select a company
Yii::app()->user->setFlash('company_error', "Please select a company.");
} elseif ($_POST['Management']['site_id'] == '') {
//error please select a site
Yii::app()->user->setFlash('site_error', "Please select a site.");
Yii::app()->user->setFlash('cid', $_POST['Management']['company_id']);
} elseif ($model->save()) {
$this->redirect(array('view', 'id' => $model->id));
}
}
$this->render(
'create',
array(
'model' => $model,
'update' => ''
)
);
}
Your view can probably stay how it is.
To improve this even further you should handle validation in your model as in :
public function rules()
{
return array(
array('company_id, site_id', 'required'),
);
}
and then all you would need to do in your action is :
public function actionCreate()
{
$model = new Management;
if (isset($_POST['Management'])) {
$model->attributes = $_POST['Management'];
if ($model->validate() && $model->save()) {
$this->redirect(array('view', 'id' => $model->id));
}
}
$this->render(
'create',
array(
'model' => $model,
'update' => ''
)
);
}
I figured out finally, this is how it worked for me:
public function actionCreate()
{
$model=new Management;
if(isset($_POST['Management']))
{
if($_POST['Management']['company_id']==''){
//error please select a company
Yii::app()->user->setFlash('company_error',"Please select a company.");
$this->redirect(array('create'));
}else{
if($_POST['Management']['site_id']==''){
//error please select a site
Yii::app()->user->setFlash('site_error',"Please select a site.");
$model->company_id = $_POST['Management']['company_id'];
$this->render('create',array(
'model'=>$model,
'update'=>'',
));
exit;
}else{
//save
$model->attributes=$_POST['Management'];
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
}
}
$this->render('create',array(
'model'=>$model,'update'=>''
));
}
I would like to show my custom error msg with rule validation fail error msg. How can I do it?
this set msg from controller
$expire_date_error = '<p>Please enter the company license expire date more than notification days</p>
<ul>
<li>Expire Date is less than notificaion days on current date.</li>
</ul>';
Yii::app()->user->setFlash('expire_date_error',$expire_date_error);
$this->render('create',array(
'model'=>$model,
this get msg from view.
<?php if(Yii::app()->user->hasFlash('expire_date_error')):?>
<div class="errorMessage">
<?php echo Yii::app()->user->getFlash('expire_date_error'); ?>
</div>
<?php endif; ?>
I used some code from http://www.yiiframework.com/wiki/21/how-to-work-with-flash-messages/
regards
=======================+++++++++++++++++++++++++++++++++==========================
Update question.
This is my controller
public function actionCreate()
{
$model=new CompanyLicense;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['CompanyLicense']))
{
$currentTime = date('Y-m-d h:i:s', time());
$model->attributes= $_POST['CompanyLicense'];
$model->created = $currentTime;
$model->active = 1;
$model->expire_date= $_POST['CompanyLicense']['expire_date'];
if($model->checkExpireDate())
{
$model->file_name=CUploadedFile::getInstance($model,'file_name');
$folder = Yii::getPathOfAlias('webroot').'/images/';
if($model->save())
{
mkdir($folder.$model->id);
$model->file_name->saveAs($folder. $model->id . "/" . $model->file_name);
$this->redirect(array('view','id'=>$model->id));
}
}else{
//echo 'debug';
$expire_date_error = '<p>Please enter the company license expire date more than notification days</p>
<ul>
<li>Expire Date is less than notificaion days on current date.</li>
</ul>';
Yii::app()->user->setFlash('expire_date_error',$expire_date_error);
}
}
$this->render('create',array(
'model'=>$model,
));
}
public function checkExpireDate($attribute='',$params ='')
{
$currentTime = date('Y-m-d', time());
$currentTime = date('Y-m-d', strtotime($currentTime . '+ ' . $this->notification_days.' days'));
if ($currentTime > $this->expire_date)
return false;
return true;
//$this->addError($this->expire_date,'should be more ' . $this->notification_days . ' days on current date!');
}
I want to show this error with other validation failed error msg.
Please read this
http://www.yiiframework.com/wiki/1/how-to-customize-the-error-message-of-a-validation-rule/
or try
class Post extends CActiveRecord
{
public function rules()
{
return array(
array('title, content', 'required',
'message'=>'Please enter a value for {attribute}.'),
// ... other rules
);
}
}
In the above, the customized error message contains a predefined placeholder {attribute}. The CRequiredValidator (whose alias is required) will replace this placeholder with the actual attribute name that fails the validation.
If you use the custom validation function, then:
class Post extends CActiveRecord
{
public function rules()
{
return array(
array('expire_date_error', 'check'),
);
}
public function check()
{
if($this->a > $this->b) {
$this->addError('expire_date_error', 'New custom error message');
return false;
}
return true;
}
}