Codeigniter Custom Form Validation Rules - php

i'm trying to make a custom validation rules for a field. It's a multiple checkbox.
<div class="row checkbox-wrapper" id="checkbox-wrapper">
<?php foreach ($facilities as $facility) : ?>
<div class="col-md-6 mb-2">
<div class="custom-control custom-checkbox">
<input type="checkbox" name="list_facility[]" value="<?php echo $facility['id']; ?>">
<label class="custom-control-label"><?php echo $facility['facility_name'] ?></label>
</div>
</div>
<?php endforeach ?>
</div>
So i try to validate them with a custom rule called facility_valdation()
$this->form_validation->set_rules('list_facility', 'Facility List', 'callback_facility_validation');
public function facility_validation($array)
{
if ($array == NULL) {
$this->form_validation->set_message('facility_validation', 'Fasilitas tidak boleh kosong (minimal = 1)');
return FALSE;
} else {
return TRUE;
}
}
The false condition is correct, whenever i leave the checkbox empty, it returns the message. but if i try to check one or more box, i keep getting the false message.
I've tried to var_dump my list_facility variable and i already get what i want. It is NULL when there are no checkbox checked, or an array of id for every checkbox i checked.
I've implemented the custoiom validation in another controller and it works just fine

Your form input field is array, so your validate field must be an array too. It should be
$this->form_validation->set_rules('list_facility[]', 'Facility List', 'callback_facility_validation');
list_facility[] instead of list_facility
I've tried and it works. Hope this helps

Related

php laravel ->status check button's value does not go to database (always stays 0)

Hello, I have an adminController as below. Even though I checked the status box, it comes to the database as zero. I can't figure out why if/else block doesn't work. If I use debug i can see "on" value for checkbox
public function addPost(Request $request){
$name=$request->title;
$content=$request->content;
$status=$request->status;
if(!is_null($status)){
$status=0;
}
else{
$status=1;
}
Posts::create([
'name' =>$name,
'content' =>$content,
'status' =>$status
]);
}
addPost.php (it's my form)
<div class="form-group">
<label for="">
<input type="checkbox" name="status" id="status">Status
</label>
</div>
As I can see you are checking the !is_null on the code, because of which you are getting the 0 if you are checking the checkbox, the condition should be like this:
if(is_null($status)){
$status=0;
}
else{
$status=1;
}
if you are still confused about this then pass a value from the checkbox and check that value in the controller:
<div class="form-group">
<label for="">
<input type="checkbox" name="status" id="status" value="1">Status
</label>
</div>
Now, you can check like this in the controller:
if(isset($status) && $status == 1){
$status=1;
}
else{
$status=0;
}
First problem is if(!is_null($status)) it is never null because
you can write in your migration default(0) so here we can manage with
Controller.
if($status == 0)
{
$status=1;
}
here status is default 0 so we check $status == 0 then we have to change it to 1 and if this condition is false then status value is already 1.
This may help you a little bit change:
public function addPost(Request $request){
$name=$request->title;
$content=$request->content;
//if box is checked status will be 1
if($request->status){
$status=1;
}
//if box is unchecked status will be 0
else{
$status=0;
}
Posts::create([
'name' =>$name,
'content' =>$content,
'status' =>$status
]);
}

in codeigniter, i am using same name for multiple inputs(type="text"), during submit i want to allow at least one value, how can i validate?

My code snippet:
<div class="col-sm-2">
<label>Weight</label>
<?php for($i=0;$i<4;$i++){ ?>
<input type="text" placeholder="Weight" name="weight[]" id="weight_<?php echo $i; ?>" class="form-control weight_cls" />
<?php } ?>
<div class="err"><?php echo form_error('weight[]'); ?></div>
</div>
If i use following CI validation:
$this -> form_validation -> set_rules('weight[]', 'Weight', 'required|numeric');
Then it will not allow until fill all fields..
I want to allow at least one.. how can i??
Create your own validation method :
$this->form_validation->set_rules('weight[]', 'Weight', 'callback_weight_check');
And in the same controller :
public function weight_check($weight)
{
if(count(array_filter($weight)) == 0) {
$this->form_validation->set_message('weight_check', 'Fill at least one value');
return false;
}
return true;
}
More infos : https://www.codeigniter.com/user_guide/libraries/form_validation.html#callbacks-your-own-validation-methods
Get the input form form
$weight = $this->input->post('weight'); //or get as your form
$weight is an array so you can use foreach loop to validate each element as below:
foreach($weight as $key=>$val)
{
$this->form_validation->set_rules("weight[".$key."]", "weight", 'required|numeric');
// you can have one more row as per your requirement.
}

How to display form field on condition using PHP in CodeIgniter?

I have select input in my form for manufacturers.
<div class="form-group">
<label for="manufacturer">Manufacturer</label>
<select id="manufacturerSelect" name="manufacturer" class="form-control">
<option disabled selected value> -- select an manufacturer -- </option>
<?php foreach ($manufacturers as $manufacturers_item): ?>
<option value="<?=$manufacturers_item['id'];?>" <?php echo set_select('manufacturer',$manufacturers_item['id'], ( !empty($manufacturer) && $manufacturer == $manufacturers_item['id'] ? TRUE : FALSE )); ?> ><?=$manufacturers_item['name'];?></option>
<?php endforeach; ?>
<option disabled>──────────</option>
<option value="24" <?php echo set_select('manufacturer','24', ( !empty($manufacturer) && $manufacturer == '24' ? TRUE : FALSE )); ?> >Other</option>
</select>
<?php echo form_error('manufacturer'); ?><br />
</div>
If "other" (value == 24) is checked additional input is asked:
$('body').on('change', '#manufacturerSelect', function() {
if ($(this).val() == 24) {
$("#otherManufacturerSelect").removeClass('hidden');
} else {
$("#otherManufacturerSelect").addClass('hidden')
}
});
And HTML:
<div id="otherManufacturerSelect" class="form-group">
<label for="otherManufacturer" >What is it then?</label>
<input type="text" name="otherManufacturer" class="form-control">
<?php echo form_error('otherManufacturer'); ?><br />
</div>
CSS:
.hidden {
display: hidden;
}
Now if user picks "other" as manufacturer addition input is displayed. Form validation rule for otherManufacturer is added in server side if manufacturer == 24. The problem is that the other manufacturer input is displayed every time user get response from server. I could add class="hidden" by default to other manufacturer div but if the form validation doesnt run other manufacturer field will not be displayed again to user.
What I need is PHP IF condition inside:
<div id="otherManufacturerSelect" <?php if(/*???*/):?>class="hidden"<?php endif; ?> class="form-group">
So that class="hidden" would be added only if manufacturer is not "other". but I cannt think of rigth condition.
Any help would be appreciated!
EDIT
Controller:
public function create()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('manufacturer', 'Manufacturer', 'required');
if($this->input->post('manufacturer') == '24'){
$this->form_validation->set_rules('otherManufacturer', 'Other manufacturer', 'required');
}
$data['manufacturers'] = $this->puzzles_model->getManufacturers();
if ($this->form_validation->run() === FALSE)
{
$this->load->view('puzzles/create', $data);
}
else
{
/* do the upload, return upload errors or save in db*/
}
}
In your particular case this would fix the problem:
<div id="otherManufacturerSelect" class="form-group <?php if(isset($manufacturer) && $manufacturer !== '24') { echo 'hidden'; } ?> ">
<label for="otherManufacturer" >What is it then?</label>
<input type="text" name="otherManufacturer" class="form-control">
<?php echo form_error('otherManufacturer'); ?><br />
</div>
Then you can remove the JS snippet. The additional form will be hidden on server side (class="hidden" will be set).
I saw that you're using var $manufacturer in the same template. I can't see your controller and how you're passing variables but instead of $manufacturer you can also use $_GET['manufacturer'] or $_POST['manufacturer'] (depending on your form action method).
Notice: $_GET['manufacturer'], $_POST['manufacturer'] and $_REQUEST['manufacturer'] is NOT sanitized input. When using $manufacturer I assume that it's sanitized in your controller.

variable in codeigniter controller never accessible to view template when re-populating input form

I've exhausted all research endpoints (docs, Google, SO, etc.), so I've been driven to ask this question publicly. The very nature of my problem should have been solved by the CodeIgniter 3.0.6 official documentation in the section entitled "Adding Dynamic Data to the View" as I (think) I'm dealing with a variable never making the scope of my controller to be accessed by my view.
I'm adding a single, custom modification to a content publishing app consisting of an edit page fetching content by ID for table data update. 1st, the form;
EDIT.PHP
<div class="row">
<div class="col-md-12">
<h3>Update post</h3>
<form method="post" action="<?php echo base_url('post/update'); ?>" enctype="multipart/form-data">
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" id="title" placeholder="News title" value="<?php echo $data['post']->title; ?>" class="form-control" />
</div>
<div class="form-group">
<label for="category">Category</label>
<select name="category" id="category" class="form-control">
<?php foreach($data['categories'] as $category): ?>
<option value="<?php echo $category->idcategory; ?>" <?php echo set_select('category', $category->idcategory); ?>><?php echo $category->title; ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="image">Image</label>
<input type="file" name="image" id="image" class="form-control" placeholder="Upload an image" />
</div>
<div class="form-group">
<label for="body">Post detail</label>
<textarea name="body" id="body" class="form-control" placeholder="Provide news content. Basic HTML is allowed."><?php echo $data['post']->body; ?></textarea>
</div>
<div class="form-group">
<label for="tags">Tags</label>
<input type="text" name="tags" id="tags" value="<?php echo set_value('tags'); ?>" class="form-control" placeholder="Comma separated tags" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
I've edited the input values to target the values I need the form populated with in the cases of the Title and Post detail inputs (didn't need to alter anything for the category input, as it's a dropdown working brilliantly), and leaving the tags form input as is to not break output layout while I troubleshoot. Controller/function Post.php was duped from original 'add' function, and I'm including the entirety rather than what I feel is the problematic code chunk;
UPDATE FUNCTION
public function update($idpost) {
$this->load->helper('form');
$data['title'] = 'Update post | News Portal';
$data['post'] = $this->posts->get($idpost);
$this->load->model('category_model', 'cm');
$data['categories'] = $this->cm->get_all();
$this->load->library('form_validation');
$this->form_validation->set_rules('title', 'title', 'trim|required');
$this->form_validation->set_rules('body', 'post body', 'trim|required');
$this->form_validation->set_rules('tags', 'tags', 'required');
if($this->input->method(TRUE) == 'POST' && $this->form_validation->run()) {
$config['upload_path'] = './assets/uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '2000';
$config['max_width'] = '2000';
$config['max_height'] = '1200';
$config['encrypt_name'] = TRUE;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('image')) {
$this->template->alert(
$this->upload->display_errors(),
'danger'
);
} else {
$upload_data = $this->upload->data();
$idpost = $this->posts->add(array(
'iduser' => $this->user->id(),
'title' => $this->input->post('title'),
'body' => $this->input->post('body'),
'image' => $upload_data['file_name']
));
$tags = $this->input->post('tags');
if(strlen($tags) > 0) {
$this->load->model('tag_model', 'tm');
$tags = explode(',', trim($tags));
$tags = array_map(array($this->tm, 'set_tag'), $tags);
$this->load->model('post_tag_model', 'ptm');
foreach($tags as $idtag) {
$this->ptm->add(array(
'idpost' => $idpost,
'idtag' => $idtag
));
}
}
$idcategory = $this->input->post('category');
if($idcategory) {
$this->load->model('post_category_model', 'pcm');
$this->pcm->add(array(
'idpost' => $idpost,
'idcategory' => $idcategory
));
}
$this->template->alert(
'Updated news item successfully',
'success'
);
redirect('post');
return;
}
}
$this->template->view('post/edit', $data);
}
This variable ($tags) is somehow lost between the controller and view, confirmed by using var_dump($this->_ci_cached_vars); to check all available objects within that corresponding view. I just need the variable $tags to repopulate with the data appropriate to the form input. How is it that there was no initialization of $tags within this function?
I COMPLETELY understand that the variable WILL NEVER be passed to the corresponding view because it's non-existant (as confirmed by my previous var_dump), but I'm lost as to how exactly to draw $tags within function scope so it can help form input to retrieve targeted data? All the other inputs are repopulating as needed. And, as an aside, I actually tracked down the original developer of this project and conferred with him on this. I tried to wrangle two approaches he outlined, but I ended up getting blank or erroring pages. The closest I could come theoretically to his second point - adapting a bit of code already in the news view partial;
<?php
if($tags = get_tags($data['news']->idpost)) {
echo '<div class="tags">';
echo 'Terms: ';
foreach($tags as $tag) {
echo ' <i class="fa fa-fw fa-link"></i> ' . $tag->title . ' ';
}
echo '</div>';
}
?>
which always ends in Undefined Index/Variable or some other damnable error message that I try to break my neck to solve, but just keep sinking further into the quagmire (lol!). It SEEMS simple to me, the basis of my problem, but I keep going around, and around, and around until I'm drunk dizzy and ten time more lost than I started out. Could someone provide a crumb of understanding?
I mean, I'm getting a conniption fit as it should be as simple as the answer provided here # Passing variable from controller to view in CodeIgniter. But, alas, 'tis not...thanks in advance for any clarificative leads.
#DFriend - I'm not wanting to alter the structure too much as ;
a) the code this is duped from is working and the only goal is to pull data from the appropriate table into that form input,
b) I don't want to disturb current functionality or inadvertently open another issue, and,
c) I'm trying to zero in on the correct elements.
Thank you for your time and answer, #DFriend.
I believe that the reason for your problems is because of the redirect call. By calling that you are essentially putting a new URL into the browser. Websites are stateless. Without using sessions or other means each request for a URL is unique. So by calling redirect you are wiping any knowledge of $tags from existence.
You can probably get around this by pushing $tags into the $_SESSION array and then checking for and retrieving it in the post controller.
Alternately, if post() is in the same controller you can simple call it instead of the redirect. post() will have be modified to accept an argument, or $tags will have to be a property of the controller class.
So to call directly to post, instead of
redirect('post');
return;
do this
$this->post($tags);
return;
Then define post to accept an optional argument
public function post($tags=null){
//somewhere in here
if(isset($tags)){
//$data is sent to views
$data['tags'] = $tags;
}
}
Expanded Answer:
How to implement a Post/Read/Get pattern in Codeigniter and still use field validation and repopulated form fields.
Using Codeigniter (CI) to implement a PRG pattern for processing requires an extension of the CI_Form_validation class. The code that follows should be in /application/libraries/MY_Form_validation.php
<?php
/**
* The base class (CI_Form_validation) has a protected property - _field_data
* which holds all the information provided by validation->set_rules()
* and all the results gathered by validation->run()
* MY_Form_validation provides a public 'setter' and 'getter' for that property.
*
*/
class MY_Form_validation extends CI_Form_validation{
public function __construct($rules = array())
{
parent::__construct($rules);
}
//Getter
public function get_field_data() {
return $this->_field_data;
}
//Setter
public function set_field_data($param=array()){
$this->_field_data = $param;
}
}
Without the template library you are using I fell back on $this->load->view(). And without access to your models and associated data I had to make some assumptions and, in some cases, leave db calls out.
Overall, I tried not to alter the structure too much. But I also wanted to demonstrate a couple handy uses of the form helper functions.
for the most part the restructuring I did was mostly an attempt at providing a clear example. If I succeed as showing the concepts you should be able to implement this fairly easily.
Here's the revised view. It makes more use of the 'form' helper functions.
<head>
<style>
.errmsg {
color: #FF0000;
font-size: .8em;
height: .8em;
}
</style>
</head>
<html>
<body>
<div class="row">
<div class="col-md-12">
<h3>Update post</h3>
<?php
echo form_open_multipart('posts/process_posting');
echo form_hidden('idpost', $idpost);
?>
<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" id="title" placeholder="News title" value="<?php echo $title; ?>" class="form-control" />
<span class="errmsg"><?php echo form_error('title'); ?> </span>
</div>
<div class="form-group">
<label for="category">Category</label>
<?php
echo form_dropdown('category', $categories, $selected_category, ['class' => 'form-control']);
?>
</div>
<div class="form-group">
<label for="image">Image</label>
<input type="file" name="image" id="image" class="form-control" placeholder="Upload an image" />
</div>
<div class="form-group">
<label for="body">Post detail</label>
<textarea name="body" id="body" class="form-control" placeholder="Provide news content. Basic HTML is allowed."><?php echo $body; ?></textarea>
<span class="errmsg"><?php echo form_error('body'); ?> </span>
</div>
<div class="form-group">
<label for="tags">Tags</label>
<input type="text" name="tags" id="tags" value="<?php echo $tags ?>" class="form-control" placeholder="Comma separated tags" />
<span class="errmsg"><?php echo form_error('tags'); ?> </span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<?= form_close(); ?>
</div>
</div>
</body>
</html>
The crux of this solution is to store form_validation->_field_data in the session when validation fails. The view loading function looks for a failure flag in session data and, if the flag is true, restores form_validation->_field_data to the current form_validation instance.
I tried to put a lot of explanation in the comments. What follows in the controller complete with display and processing methods.
class Posts extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('session');
$this->load->library('form_validation', NULL, 'fv');
}
/**
* post()
* In this example the function that shows the posting edit page
* Note the use of the optional argument with a NULL default
*/
function post($idpost = NULL)
{
$this->load->model('category_model', 'cm');
$categories = $this->cm->get_all();
/*
* Your model is returning an array of objects.
* This example is better served by an array of arrays.
* Why? So the helper function form_dropdown() can be used in the view.
*
* Rather than suggest changing the model
* these lines make the conversion to an array of arrays.
*/
$list = [];
foreach($categories as $category)
{
$list[$category->idcategory] = $category->title;
}
$data['categories'] = $list; // $data is used exclusivly to pass vars to the view
if(!empty($idpost))
{
//if argument is passed, a database record is retrieved.
$posting = $this->posts->get($idpost);
//Really should test for a valid return from model before using it.
//Skipping that for this example
$title = $posting->title;
$body = $posting->body;
//assuming your model returns the next two items like my made up model does
$selected_category = $posting->category;
$tags= $posting->tags;
}
else
//a failed validation (or a brand new post)
{
//check for failed validation
if($this->session->failed_validation)
{
// Validation failed. Restore validation results from session.
$this->fv->set_field_data($_SESSION['validated_fields']);
}
}
//setup $data for the view
/* The 'idpost' field was add to demonstrate how hidden data can be pasted to and from
* a processing method. In this case it would be useful in providing a 'where = $value'
* clause on a database update.
* Also, a lack of any value could be used indicate an insert is requried for a new record.
*
* Notice the ternary used to provide a default value to set_value()
*/
$data['idpost'] = $this->fv->set_value('idpost', isset($idpost) ? $idpost : NULL);
$data['title'] = $this->fv->set_value('title', isset($title) ? $title : NULL);
$data['body'] = $this->fv->set_value('body', isset($body) ? $body : NULL);
$data['tags'] = $this->fv->set_value('tags', isset($tags) ? $tags : NULL);
$data['selected_category'] = $this->fv->set_value('category', isset($selected_category) ? $selected_category : '1');
$this->load->view('post_view', $data);
}
public function process_posting()
{
if($this->input->method() !== 'post')
{
//somebody tried to access this directly - bad user, bad!
show_error('The action you have requested is not allowed.', 403);
// return; not needed because show_error() ends with call to exit
}
/*
* Note: Unless there is a rule set for a field the
* form_validation->_field_data property won't have
* any knowledge of the field.
* In Addition, the $_POST array from the POST call to the this page
* will be GONE when we redirect back to the view!
* So it won't be available to help repopulate the <form>
*
* Rather than making a copy of $_POST in $_SESSION we will rely
* completely on form_validation->_field_data
* to repopulate the form controls.
* That can only work if there is a rule set
* for ANY FIELD you want to repopulate after failed validation.
*/
$this->fv->set_rules('idpost', 'idpost', 'trim'); //added any rule so it will repopulate
// in this example required would not be useful for 'idpost'
$this->fv->set_rules('title', 'title', 'trim|required');
$this->fv->set_rules('body', 'post body', 'trim|required');
$this->fv->set_rules('tags', 'tags', 'required');
//add rule for category so it can be repopulated correctly if validation fails
$this->fv->set_rules('category', 'category', 'required');
if(!$this->fv->run())
{
// Validation failed. Make note in session data
$this->session->set_flashdata('failed_validation', TRUE);
//capture and save the validation results
$this->session->set_flashdata('validated_fields', $this->fv->get_field_data());
//back to 'posts/index' with server code 303 as per PRG pattern
redirect('posts/post', 'location', 303);
return;
}
// Fields are validated
// Do the image upload and other data storage, set messges, etc
// checking for $this->input->idpost could be used in this block
// to determine whether to call db->insert or db->update
//
// When process is finished, GET the page appropriate after successful <form> post
redirect('controller/method_that_runs_on_success', 'location', 303);
}
//end Class
}
Questions? Comments? Insults?

Cant get values of checkboxes in codeigniter

Im trying to insert multiple checkboxes but cant get their values in codeigniter 2
this is my code in View
<!-- Multiple Checkboxes (inline) -->
<div class="form-group">
<div class="col-md-4">
<label class="checkbox-inline" for="checkboxes-0">
<input type="checkbox" name="checkboxes[]" id="checkboxes-0" value="22">
Пентхаус
</label>
<br>
<!-- Text input-->
<div class="form-group">
<div class="col-md-8">
<input id="cena" name="cena[]" type="text" placeholder="Въведи цена" class="form-control input-md">
</div>
</div>
<label class="checkbox-inline" for="checkboxes-1">
<input type="checkbox" name="checkboxes[]" id="checkboxes-1" value="21">
Гараж/Паркомясто
</label>
<br>
<!-- Text input-->
<div class="form-group">
<div class="col-md-8">
<input id="cena" name="cena[]" type="text" placeholder="Въведи цена" class="form-control input-md">
</div>
</div>
This is my Model:
public function InsertCheckbox() {
$property_typesRequest = $this->input->post('checkboxes');
foreach($property_typesRequest as $value){
$this->db->insert_batch('property_type_details', $property_typesRequest);
}
}
in Controller i just use this:
$this->estate_m->InsertCheckbox();
And this going insert 0 in database, when i var_dump $property_typesRequest theres shows bool(false). I cant get values of checkboxes...
EDIT...
I have try to edit my code but still no result:
public function edit()/*this is controller */
{
$data=array('column_name'=>$this->input->post('checkboxes');
$result=$this->estate_m->InsertCheckbox($data);
if($result==true)
{
echo "Success";
}
else
{
echo "Fail";
}
}
public function InsertCheckbox($data) /*this is Model */
{
$this->db->insert('property_type_details', $data);
return ($this->db->affected_rows() != 1 ) ? false : true;
}
With this edited code always gives me Succes
Form submitted values should be in multi dimension array
To achieve that your form inputs should be in multi dimension.
For insert_batch() function, the array should be in multi dimension.
In array every key must be field names in db table and value must be the form input value.
So change the form structure like the below array.
array(
array(
'checkboxes' => 'checkboxe value' ,
'cena' => 'cena values'
),
array(
'checkboxes' => 'checkboxe value' ,
'cena' => 'cena values'
)
);
Form inputs should be like below:
<input name="data[1][checkbox_columnname]" type="checkbox" value="21">Пентхаус
<input name="data[1][textbox_columnname]" type="text">
<input name="data[2][checkbox_columnname]" type="checkbox" value="22">Гараж/Паркомясто
<input name="data[2][textbox_columnname]" type="text">
And the model should not have foreach loop.
Simply pass the data as below.
$data=$this->input->post('data');
$this->db->insert_batch('mytable', $data);
Please use this code in model.
public function InsertCheckbox() {
$property_typesRequest = $this->input->post('checkboxes');
foreach($property_typesRequest as $value){
$data['columnename'] = $value;
$this->db->insert('tablename', $data);
}
}
Hope it inserts into the database
Thank you

Categories