Unable to preserve input values after form validation Codeigniter 4 - php

This is a question I have seen asked before but I have been unable to find an answer for the newer version of Codeigniter.
Controller
<?php
namespace App\Controllers;
class SendEmail extends BaseController
{
public function index($validation = NULL){
// Load form helper
helper('form');
// Instantiate session
$session = \Config\Services::session();
// Set css, javascript, and flashdata
$data = [
'css' => array('contact.css'),
'js' => array('contact.js'),
'validation' => $validation,
'success' => $session->get('success')
];
// Show views
echo view('templates/header', $data);
echo view('contact', $data);
echo view('templates/footer', $data);
}
public function sendEmail(){
// Instantiate request
$request = $this->request;
// Captcha API
$captchaUser = $request->getPost('g-recaptcha-response');
// Captcha Key loaded from a file left out of the repo
$captchaConfig = config('Config\\Credentials');
$captchaKey = $captchaConfig->captchaKey;
$captchaOptions = [
'secret' => $captchaKey,
'response' => $captchaUser
];
$client = \Config\Services::curlrequest();
$captchaResponse = $client->request('POST', 'https://www.google.com/recaptcha/api/siteverify', ['form_params' => $captchaOptions]);
$captchaObj = json_decode($captchaResponse->getBody());
// Load validation library
$validation = \Config\Services::validation();
// Set validation rules
$validation->setRules([
'name' => 'required|alpha_dash|alpha_space',
'email' => 'required|valid_email',
'subject' => 'required|alpha_numeric_punct',
'message' => 'required|alpha_numeric_punct'
]);
// Validate inputs
if (!$this->validate($validation->getRules())){
// Run index function to show the contact page again
$this->index($this->validator);
}
// Validate captcha
elseif(!$validation->check($captchaObj->success, 'required')){
$validation->setError('captcha','Did not pass captcha. Please try again.');
$this->index($validation->getErrors());
}
else{
// Set variables to input
$name = $request->getPost('name');
$email = $request->getPost('email');
$subject = $request->getPost('subject');
$message = $request->getPost('message');
// Load email class
$emailC = \Config\Services::email();
// Set email settings
$emailC->setFrom('bensirpent07#benkuhman.com', $name);
$emailC->setReplyTo($email);
$emailC->setTo('benkuhman#gmail.com');
$emailC->setSubject($subject);
$emailC->setMessage($message);
// Testing section
echo '<br>'.$name.'<br>'.$email.'<br>'.$subject.'<br>'.$message;
/* Temporarily disabled for testing purposes
// Send email
if($emailC->send(false)){
// Redirect
return redirect()->to(base_url().'/contact')->with('success', true);
}else{
// Display error
throw new \CodeIgniter\Database\Exceptions\DatabaseException();
};
*/
}
}
}
Contact View
<div class="container">
<div class="row">
<div class="col">
<div class="alert alert-success align-center" id="message-alert" <?php if($success){echo 'style="display:block"';} ?>>Message successfully sent!</div>
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-6">
<?php echo form_open('send_email', ['id'=>'contactForm'])?>
<div class="form-group">
<label for="name">Name</label>
<input name="name" type="text" class="form-control" id="name" aria-describedby="name" placeholder="Name" required>
<p class="invalid"><?php if(isset($validation)&&$validation->hasError('name')){echo $validation->getError('name');}?></p>
</div>
<div class="form-group">
<label for="email">E-Mail</label>
<input name="email" type="email" class="form-control" id="email" aria-describedby="email" placeholder="E-mail" required>
<small id="emailHelp" class="form-text">I'll never share your email with anyone else.</small>
<?php //echo $validation->email;?>
<p class="invalid"><?php if(isset($validation)&&$validation->hasError('email')){echo $validation->getError('email');}?></p>
</div>
<div class="form-group">
<label for="subject">Subject</label>
<input name="subject" type="text" class="form-control" id="subject" placeholder="Subject" required>
<p class="invalid"><?php if(isset($validation)&&$validation->hasError('subject')){echo $validation->getError('subject');}?></p>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea name="message" rows="5" class="form-control" id="message" placeholder="Type your message here." required></textarea>
<p class="invalid"><?php if(isset($validation)&&$validation->hasError('message')){echo $validation->getError('message');}?></p>
</div>
<button id="submitButton" type="submit" class="btn btn-primary g-recaptcha" data-sitekey="6Ldf07AZAAAAAAflQCaJcWgGFCWevCswpIrm0mJN" data-callback='onSubmit' data-action='submit'>Submit</button>
<p class="invalid"><?php if(isset($validation)&&$validation->hasError('captcha')){echo $validation->getError('captcha');}?></p>
<?php echo form_close()?>
</div>
</div>
</div>
<script>
function onSubmit(token) {
document.getElementById("contactForm").submit();
}
</script>
<script src="https://www.google.com/recaptcha/api.js"></script>
From my understanding of the way validation used to work in CodeIgniter, is that when you loaded your view after a form validation it would update the values with what was previously entered. This does not seem to be the case for CodeIgniter 4. I've also tried directly loading the views rather than calling the index function on validation fail. Still would not fill in the form values.
Now I could just pass these values to the index function via $data array. Which is the fix I'm going to use for now. This is more so a sanity check to see if there is something basic I'm missing or if I'm incorrectly using the validation format for CodeIgniter 4.

in CI4 you can use old() function to preserve the input value upon form validation:
View file:
<input type="tel" name="phone" value="<?= old('phone'); ?>">
In Controller you must use withInput() in the redirect() code:
$validation = \Config\Services::validation();
$request = \Config\Services::request();
// your input validation rules
$validation->setRules(...)
if($request->getMethod() == "post" && ! $validation->withRequest($request)->run()) {
return redirect()->back()->withInput()->with('error', $this->validation->getErrors());
} else {
// form validation success
}

Related

Validator Does Not Show Errors At Blade

I have a Controller method like this:
use Validator;
public function insert(Request $request)
{
$data = Validator::make(request()->all(),[
'title' => 'required',
'name' => 'required|alpha_num',
'activation' => 'nullable',
'cachable' => 'nullable'
])->validated();
$wallet = new Wallet();
$wallet->title = $data['title'];
$wallet->name = $data['name'];
if (!empty($data['activation'])) {
$wallet->is_active = 1;
} else {
$wallet->is_active = 0;
}
if (!empty($data['cachable'])) {
$wallet->is_cachable = 1;
} else {
$wallet->is_cachable = 0;
}
$wallet->save();
return redirect(url('admin/wallets/index'));
}
And then I tried showing errors like this:
#error("name")
<div class="alert alert-danger">{{$message}}</div>
#enderror
But the problem is, it does not print any error when I fill the form incorrectly.
So how to fix this and show errors properly?
Here is the form itself, however it submits data to the DB correctly:
<form action="{{ route('insertWallet') }}" method="POST" enctype="multipart/form-data">
#csrf
<label for="title" class="control-label">Title</label>
<br>
<input type="text" id="title-shop" name="title" class="form-control" value="" autofocus>
#error("title")
<div class="alert alert-danger">{{$message}}</div>
#enderror
<label for="title" class="control-label">Name</label>
<br>
<input type="text" id="title-shop" name="name" class="form-control" value="" autofocus>
#error("name")
<div class="alert alert-danger">{{$message}}</div>
#enderror
<input class="form-check-input" type="checkbox" name="cachable" value="cashable" id="cacheStatus">
<label class="form-check-label" for="cacheStatus">
With Cash
</label>
<input class="form-check-input" type="checkbox" name="activaton" value="active" id="activationStatus">
<label class="form-check-label" for="activationStatus">
Be Active
</label>
<button class="btn btn-success">Submit</button>
</form>
check the official documentation here
add the following code
if($data->fails()){
return redirect(url('admin/wallets/index'))->withErrors($data)->withInput();
}
And after that save your data in your database
You are not returning any errors, you are just redirecting back to the view without any data.
Your fix would be to have your validator as this:
$data = Validator::validate(request()->all(),[
'title' => 'required',
'name' => 'required|alpha_num',
'activation' => 'nullable',
'cachable' => 'nullable'
]);
See that I have changed Validator::make to Validator::validate. As the documentation states:
If the validation rules pass, your code will keep executing normally; however, if validation fails, an exception will be thrown and the proper error response will automatically be sent back to the user.
If validation fails during a traditional HTTP request, a redirect response to the previous URL will be generated. If the incoming request is an XHR request, a JSON response containing the validation error messages will be returned.
So, if your validation passes, it will save all the validated data into $data, as you did with ->validated() (but you don't have to write it here), and if it fails, it will automatically throw an Exception, in this case ValidationException, so Laravel will automatically handle it and redirect back with to the same URL and with the errors. So it now should work...
This is the Validator::validate source code and this is the validate source code for the validator validate method.

how to redirect and show error validateion in laravel

good day,
I new in laravel Framework and I face this two problems : -
first one
I want to redirect to my page after 2 seconds automatically.
the second one
I make custom function call (is exist )
if this function returns true data I want to print "name exist before " but the problem here is form was rested when this function returns true and print message.
how to prevent form resetting from inputs value?
here is my code
controller code
enter code here
public function add(Request $request)
{
// start add
if($request->isMethod('post'))
{
if(isset($_POST['add']))
{
// start validatio array
$validationarray=$this->validate($request,[
//'name' =>'required|max:25|min:1|unique:mysql2.products,name|alpha',
'name' =>'required|alpha',
'price' =>'required|numeric',
]);
// check name is exist
if(true !=dBHelper::isExist('mysql2','products','`status`=? AND `deleted` =? AND `name`=?',array(1,1,$validationarray['name'])))
{
$product=new productModel();
// start add
$product->name=$request->input('name');
$product->save();
$add=$product->id;
$poducten=new productEnModel();
$poducten->id_product=$add;
$poducten->name=$request->input('name');
$poducten->price=$request->input('price');
$poducten->save();
$dataview['message']='data addes';
}else{
$dataview['message']='name is exist before';
}
}
}
$dataview['pagetitle']="add product geka";
return view('productss.add',$dataview);
}
this is my routes
Route::get('/products/add',"produtController#add");
Route::post('/products/add',"produtController#add");
this is my view
#extends('layout.header')
#section('content')
#if(isset($message))
{{$message}}
#endif
#if(count($errors)>0)
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
</ul>
</div>
#endif
<form role="form" action="add" method="post" enctype="multipart/form-data">
{{csrf_field()}}
<div class="box-body">
<div class="form-group{{$errors->has('name')?'has-error':''}}">
<label for="exampleInputEmail1">Employee Name</label>
<input type="text" name="name" value="{{Request::old('name')}}" class="form-control" id="" placeholder="Enter Employee Name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email Address</label>
<input type="text" name="price" value="{{Request::old('price')}}" class="form-control" id="" placeholder="Enter Employee Email Address">
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="add" class="btn btn-primary">Add</button>
</div>
</form>
#endsection
I hope that I understood your question.
Instead of using {{ Request::old('price') }} use {{ old('price') }}
This should retrieve the form data after page was reloaded.
Try the below the code for error display in view page
$validator = Validator::make($params, $req_params);
if ($validator->fails()) {
$errors = $validator->errors()->toArray();
return Redirect::to($web_view_path)->with('errors', $errors);
}
You want to automatically redirect to another page submit the form using ajax and use below the settimeout menthod.
setTimeout(function(){ // Here mentioned the redirect query }, 3000);
//use $request instead of $_POST
if($request->isMethod('post'))
{
if(isset($request['add']))
{
// start validatio array
$validationarray=$this->validate($request,[
//'name' =>'required|max:25|min:1|unique:mysql2.products,name|alpha',
'name' =>'required|alpha',
'price' =>'required|numeric',
]);
// check name is exist

form input cleared after submit data using laravel fram work

I have multiple data base connection when I validate name of product I send message product name is exist before to view and here problem is appeared.
Message appeared in view but all form inputs is cleared.
How I recover this problem taking in consideration if product name not exist. validation executing correctly and if found error in validation it appeared normally and form input not cleared.
this my controller code.
public function add(Request $request)
{
// start add
if($request->isMethod('post'))
{
if(isset($_POST['add']))
{
// start validatio array
$validationarray=$this->validate($request,[
//'name' =>'required|max:25|min:1|unique:mysql2.products,name|alpha',
'name' =>'required|alpha',
'price' =>'required|numeric',
]);
// check name is exist
$query = dBHelper::isExist('mysql2','products','`status`=? AND `deleted` =? AND `name`=?',array(1,1,$validationarray['name']));
if(!$query) {
$product=new productModel();
// start add
$product->name = $request->input('name');
$product->save();
$add = $product->id;
$poducten = new productEnModel();
$poducten->id_product = $add;
$poducten->name = $request->input('name');
$poducten->price = $request->input('price');
$poducten->save();
$dataview['message'] = 'data addes';
} else {
$dataview['message'] = 'name is exist before';
}
}
}
$dataview['pagetitle']="add product geka";
return view('productss.add',$dataview);
}
this is my view
#extends('layout.header')
#section('content')
#if(isset($message))
{{$message}}
#endif
#if(count($errors)>0)
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
</ul>
</div>
#endif
<form role="form" action="add" method="post" enctype="multipart/form-data">
{{csrf_field()}}
<div class="box-body">
<div class="form-group{{$errors->has('name')?'has-error':''}}">
<label for="exampleInputEmail1">Employee Name</label>
<input type="text" name="name" value="{{Request::old('name')}}" class="form-control" id="" placeholder="Enter Employee Name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email Address</label>
<input type="text" name="price" value="{{Request::old('price')}}" class="form-control" id="" placeholder="Enter Employee Email Address">
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="add" class="btn btn-primary">Add</button>
</div>
</form>
#endsection
this is my route
Route::get('/products/add',"produtController#add");
Route::post('/products/add',"produtController#add");
You can create your own custom validate function like below. I guess this should help you.
Found it from https://laravel.com/docs/5.8/validation#custom-validation-rules -> Using Closures
$validationarray = $this->validate($request,
[
'name' => [
'required',
'alpha',
function ($attribute, $value, $fail) {
//$attribute->input name, $value for that value.
//or your own way to collect data. then check.
//make your own condition.
if(true !=dBHelper::isExist('mysql2','products','`status`=? AND `deleted` =? AND `name`=?',array(1,1,$value))) {
$fail($attribute.' is failed custom rule. There have these named product.');
}
},
],
'price' => [
'required',
'numeric',
]
]);
First way you can throw validation exception manually. Here you can find out how can you figure out.
Second way (I recommend this one) you can generate a custom validation rule. By the way your controller method will be cleaner.

codeigniter form not submitting data

I have tried everything I can think of but whenever I click submit the form passes on a null value, I dont know if it is the problem with the form or the controller or even the view. I changed this->input->post to posted data and i get an error of undefined variable posted data, please help.
Controller:
public function addmenu(){
$this->load->model('organizer_model');
$data = array(
'menu_name' => $this->input->post('menu name'),
'price' => $this->input->post('price'),
'email' => $this->session->userdata('email')
);
if($this->organizer_model->insertmenu($data)) {
$this->session->set_flashdata('message', 'Your menu has been added');
redirect('/menu/index', 'refresh');
} else {
$this->session->set_flashdata('message', 'Your menu was not added, please try again');
redirect('/menu/index', 'refresh');
}
View:
<form action="<?php echo site_url('Organizer/addmenu'); ?>" method="post" class="form-horizontal no-margin">
<div class="control-group">
<label class="control-label" for="menuname">
Menu Name
</label>
<div class="controls controls-row">
<input class="span3" name="data[menuname]" type="text" placeholder="Enter menu Name">
</div>
</div>
<div class="control-group">
<label class="control-label" for="price">
Price
</label>
<div class="controls controls-row">
<input class="span3" name="data[price]" type="text" placeholder="">
</div>
</div>
<div class="form-actions no-margin">
<button type="submit" name="submit" class="btn btn-info pull-right">
Add menu
</button>
<div class="clearfix">
</div>
</div>
</form>
Model:
public function insertmenu($data) {
$condition = "email = '" . $data['email'] . "'";
$this->db->select('organizer_id');
$this->db->from('organizer');
$this->db->where($condition);
$this->db->limit(1);
$query = $this->db->get();
if ($query->num_rows() > 0){
array_pop($data); //will remove email from data
$row = $query->row();
$data['organizer_id'] = $row->organizer_id;
$this->db->insert('menu', $data);
if ($this->db->affected_rows() > 0) {
return true;
} else {
return false;
}
} else {
return false;
}
}
I notice same question here codeigniter- insert data into db not working
Checks
Make sure you load your form helper and url helper.
Make sure you use form validation when submitting form in codeigniter on controller.
From this php user guide here http://php.net/manual/en/reserved.variables.post.php
Example on your input would be like person[0][first_name]
<form action="" method="">
<input type="text" name="data_posts[0][menu_name]" placeholder="Enter menu Name">
<input type="text" name="data_posts[0][price]" placeholder="">
</form>
Model
<?php
class Model_something extends CI_Model {
public function add_menu() {
$data_posts = $this->input->post('data_posts');
foreach ($data_posts as $data_post) {
$data = array(
'email' => $this->session->userdata('email'),
'menu_name' => $data_post['menu_name'],
'price' => $data_post['price']
);
$this->db->insert('tablename', $data);
}
}
}
Controller
<?php
class Add_menu extends CI_Controller {
public function index() {
$this->load->helper('form');
$this->load->helper('url');
$this->load->library('form_validation');
$data_posts = $this->input->post('data_posts');
foreach ($data_posts as $data_post) {
$this->form_validation->set_rules('data_posts['.$data_post.'][menu_name]', 'Menu Name', 'required');
$this->form_validation->set_rules('data_posts['.$data_post.'][price]', 'Price', 'required');
}
if ($this->form_validation->run() == FALSE) {
$this->load->view('some_view');
} else {
$this->load->model('model_something');
$this->model_something->add_menu();
redirect('to_success_page');
}
}
}
You could also check if has been inserted by using callback function
Codeigniter 3 user guide form validation http://www.codeigniter.com/user_guide/libraries/form_validation.html
Codeigniter 2 user guide form validation http://www.codeigniter.com/userguide2/libraries/form_validation.html
Also you should upgrade to the new bootstrap I see your using old version.

CodeIgniter `validation_errors()` is not working

I am using version CodeIgniter 2.1.4. I have problem on displaying form validation error. form validation is returning false but validation_errors() is not displaying any errors. I have tried to echo in controller and in view but no result. I am giving request through ajax.no php errors are thrown.
Controller:
<?php
class Dashboard extends Admin_Controller {
public function ajax_new_dist_center($id=NULL)
{
$this->load->model('dist_centre_m');
$this->load->helper(array('form', 'url'));
$this->load->library('Form_validation');
$validation = $this->dist_centre_m->rules;
$this->form_validation->set_error_delimiters('<li>', '</li>');
$this->form_validation->set_rules($validation);
if ($this->form_validation->run() == TRUE)
{
if($this->dist_centre_m->create($id))
echo 'New centre created';
else
{
$this->output->set_status_header('404');
echo 'Given center not found';
}
}
else
{
$this->output->set_status_header('400');
echo 'validation Failed';
$this->load->view('alert_error');
}
}
}
View:
<?php echo validation_errors();?>
<p>Testing Error</p>
Model:
class dist_centre_m extends MY_Model {
protected $_table_name = 'distribution_centre';
protected $_primary_key = 'dis_id';
protected $_order_by = 'dis_id';
public $rules = array(
'name' => array(
'field'=>'name',
'label'=>'Center name',
'rules'=>'trim|required|xss_cleaned|min_length[3]|max_length[45]'
),
'street' => array(
'field'=>'street',
'label'=>'Street',
'rules'=>'trim|required|xss_cleaned|min_length[3]|max_length[45]'
),
'town' => array(
'field'=>'town',
'label'=>'Town',
'rules'=>'trim|required|min_length[3]|max_length[45]|required|xss_cleaned'
),
'postcode' => array(
'field'=>'postcode',
'label'=>'Postcode',
'rules'=>'trim|required|max_length[10]|required|xss_cleaned'
),
'tel' => array(
'field'=>'tel',
'label'=>'Telephone number',
'rules'=>'trim|valid|exact_length[11]|required|xss_cleaned'
),
);
public function __construct() {
parent::__construct();
$this->load->helper('security');
}
public function create($id=NULL){
$data = array(
'name' =>$this->input->post('name',true),
'street' =>$this->input->post('street',true),
'town' =>$this->input->post('town',true),
'postcode' =>$this->input->post('postcode',true),
'tel' =>$this->input->post('tel',true),
);
return $this->save($data,$id);
}
}
Output:
validation Failed
Testing Error
None of the related question is working please do not mark duplicate.
Update:
My Ajax request page:
<form id="new-center-form" method="post">
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" placeholder="Name"/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for='street'>Street</label>
<input type="text" name="street" placeholder="Street"/>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="town">Town</label>
<input type="text" name="town" placeholder="Town"/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="postcode">Postcode</label>
<input type="text" name="postcode" placeholder="Postcode"/>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="tel">Phone</label>
<input type="text" name="tel" placeholder="Telephone"/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<button id="centre-submit" class="btn btn-primary pull-left">Save</button>
</div>
</div>
</div>
</form>
<script type="text/javascript">
$(document).ready(function(){
var url_new_center = '<?php echo page_url('new-center') ?>';
$('#centre-submit').click(function(e){
e.preventDefault();
$.ajax({
url:url_new_center,
type:'post',
data: $('new-center-form').serialize()
}).done(function(response){
$('#infos').html(response);
$('#infos').slideDown();
$('.new-centre').slideUp();
}).fail(function(response){
$('#errors').html(response);
$('#errors').slideDown();
});
})
});
</script>
Finally after a long sleep I figured out.$this->form_validation->run() returns false when no $_POST data found and it will not set any errors to print. In my ajax request due to some errors it could not send any data. Thanks for curl I was able to test it.
update
data: $('new-center-form').serialize() // this was the error.
I made a typo here. this should be like this data: $('#new-center-form').serialize()
let me make your answer more clear.
It is not because no $_POST data found like you said,
it is actually because that there are no RELATED $_POST data that you have set rules for them in your model.
There may have been any other $_POST data exclude for those that you have set rules for:
'name' , 'street' , 'town' , 'postcode' , ' tel'
then the CI validator could not find any of the elements that rules have been set so the form_validation->run() will definitely return false
And certainly the validation_errors() will not show anything because there are nothing to apply the specified rules on.

Categories