I have a couple of fields in the <form>... $fieldset is array of the fields name, it loop them with isset() checking.
I want to apply validation (eg: required input, email) to a few fields, how to apply this from my code logic?
public function actionProfile($id = null) {
$profileModel = new ProfileModel;
// <input> fields name
$fieldset['name'] = array('FirstName', 'LastName');
$fieldset['address'] = array('HouseNumber', 'StreetName', 'Town', 'Location');
$formError = array();
if (isset($_POST['profile'])) {
// Process input event
foreach ($fieldset as $legend => $fields) {
foreach ($fields as $field) {
if (!isset($_POST['profile'][$field])) {
$formError[$legend] = $field;
} else {
$form[$legend][$field] = $_POST['profile'][$field];
}
}
}
if (count($formError) == 0) {
if ($profileModel->saveAddress($form['address'])) {
//Saved to the database.
}
}
}
// Get data from the database
$data['profile'] = $profileModel->find($id);
$view = new View($this->layout, $data)->render();
}
In the view file, it would look something like this:
<input type='text' value=<?php echo $profile['first_name'] name='profile[FirstName]' ?>
<input type='text' value=<?php echo $profile['last_name'] name='profile[LastName]' ?>
Edit: When editing the record via form.. If there is an error (validation) - I want to put user input value back into <input> value instead of value from the database. How can it be done from my code?
You are currently putting validation logic inside the controller. That should go in the Domain Business Object (read more: here and here).
Also, "model" is not a class. Model is a layer in MVC architecture. This layers mostly consists of two types of instances: Domain Objects and Data Mappers. Each with quite different responsibilities.
I think it would be wise to split the verification code from the actual update function.
Have it run through a validator first, checking for length and required inputs. When that passes, you can send all that (formatted) data to the action. If it doesn't pass the validation, return it to the view with additional error information so you can guide the user to fix the problem.
I hope you understand what I'm trying to explain to you. :-).
Use the PHP Filter functions:
http://www.php.net/manual/en/ref.filter.php
Use the Variable Handlers
http://us2.php.net/manual/en/ref.var.php
Related
is there any sugestion to store default value that is posted to database from form html?
my aplication is using mysql as the rdmbs and codeigniter for backend process.
right now, i just using html method at the submit form.
<input type="hidden" id="" name="" value="">
at the html page and set the value there.
but the value is visible when you open the source code in any other browser.
is there any method to store value that is not visible from user in codeigniter?
If your form is posting the data on the same method wherefrom it is rendered then the best approach is that; keep the value in the method itself and use it after form submit.
public function edit() {
$id = 12;
if ($this->form_validation->run()) {
$dataComm = array(
'id' => $id
'name' => $this->input->post('name')
);
$result_comm = $this->Common_model->insert_data('cw_franchise_commission', $dataComm);
}
$this->data['title'] = "Edit User";
$this->load->view('edit', $this->data);
}
And if your form action is another method then you can encode the value and decode it after form submission.
To Encode
bin2hex(base64_encode($id))
To Decode
base64_decode(hex2bin($this->input->post('id')));
One more thing if you are using hidden inputs then you should name it something confusing not clear at all. Otherwise, anyone can understand the purpose of the field.
There is no such a way but you can keep it in encoding format using
base64_encode()
<input type="hidden" name="id" value="<php echo base64_encode('1231231231'.$id); ?>">
"1231231231" just for additional security which will preprend with the id
cut "1231231231" in controller like below to get the id
function abc() {
if (isset($_POST['id']) && !empty($_POST['id'])) {
$id = substr(base64_decode($_GET['id']), 10); // to remive extra string
if (!empty($id)) {
// you get id here
} else {
//if someone attempt to tamper with the id then it will retrive blank
}
} else {
//redirect or show error
}
}
I have a form that is mostly generated by a class named "buildform".
Now every part of the form validates itself on the position it is.
This looks like this:
echo $frm->create_input("customer_nr", "Customer Nr.", "text:empty:int");
The third attribute here are the conditions (here: text field, not empty only integer).
The function "create_input" calls some more function that are validating the form field directly on place when the form is submitted.
I do it this way for multiple reasons:
I can directly color the forms to red when there's an error
I only have to tell the form attributes one time instead of when creating it and validating.
This is really comfortable and until now has made creating forms very easy.
The validation errors for then the users will be stored in a class variable like this:
function add_err($n_errmsg) {
$this->errmsgs[] = $n_errmsg;
return;
}
At the end of the form I show the errors like this:
if(isset($_POST["sbm"])) {
$ret_err = $frm->ret_err();
if(!empty($ret_err)) {
echo $ret_err;
}
else {
// send success mail
}
}
This all works without any problems.
Now I had the idea to hide the form when it's submitted. But then I would have to make sure there are no errors before the form even is loaded!
I wanted to something like
else {
$hideform = true;
// send success mail
}
This currently is not possible as the errors are generated while "generating" the form fields.
If I move the errors to the top the errors are always "empty" there because the validation is done later below...
Do you have an idea how I can solve this?
Do I have to validate the forms before loading them or is there another way?
Thanks!
Best Regards
Toby
Ok, well there are a few ways to solve this.
Basically you are echoing the form html as you go along:
echo $frm->create_input(...);
echo $frm->create_input(...);
what you could do instead is save the html into a string:
$formhtml = '';
$formhtml .= $frm->create_input(...);
$formhtml .= $frm->create_input(...);
if($frm->ret_error()){
echo $formhtml;
//other logic
}else{
//send mail
}
Along the same lines, you could change your form class, so that this is done internaly, and add a show method:
private $html = '';
function create_input(...){
//retrun $ret;
$this->html .= $ret;
function show(){
echo $this->html;
}
$frm->create_input(...);
$frm->create_input(...);
if($frm->ret_error()){
$frm->show();
//other logic
}else{
//send mail
}
I have a page that has 39 check boxes. The check boxes in my example resemble form names. My problem is that with 39 check boxes I need a way to store what forms were given to a student. Currently what I have set up is that each form is separated with a comma and a quote so that when a report is run the Administrator can use a CSV download option and group which forms a student has received. This works but is very rudimentary and also gives a bad side affect that before each form name a / is present because mysql escapes quotes.
This is what I currently have :
if ($this->input->post('action') == 'additional') {
$givenforms = "";
foreach ($this->input->post('form') as $forms) {
$givenforms .= ', "' . $forms . '"';
}
$comments = 'This student was given' . $givenforms . '';
if (($this->input->post('action') == 'additional') && ($this->input->post('other') == 'OTHER')) {
$comments .= ', '.$this->input->post('counselorcomments');
}
}
Again in the database the results will look like : This student was given "xyz", "eoe", "wwo",
Pretty much I just need ideas on how to store which forms a student was given, and if needed if all 39 forms are given to a student I need to store all forms the student was given for later reporting. (even though 39 forms wont be given)
Sounds like you need a one:many relationship between students and forms. Might want to do a little research on that topic.
I consider it generally to be pretty poor form to store comma separated values in a single field in a database, if you're doing that, it's almost always a sign that you need (at least) another table.
An hour or two of refactoring what I had with the CSV paid off quite well. I am very very pleased with the reporting/analytical possibilities of the knew information and the way I got it stored now.
Couple snippets of code for any one else looking into doing something like this! :
if ($this->form_validation->run() == FALSE) { // This stuff is self explanatory RT(F)M if you will :)
$this->cont();
} else {
$this->load->model('queue_model'); // Load model
$session = $this->uri->segment(3); // Gets the session id
$counselor = $this->session->userdata('username'); // I get counsellor names from the username they log in by joining between the two tables
if ($this->input->post('action') == 'Additional') { // If additional forms is checked do the following
foreach ($this->input->post('form') as $form_id) { // for each form submitted take the session Id from above and insert it into the table forms with the foreach $form_id variable
$this->queue_model->forms($session, $form_id);
}
if (($this->input->post('action') == 'Additional') && ($this->input->post('addother') == 'addotherinfo')) { // If forms were submitted and a addotherinfo was [checked] add comments
$comments = ''.$this->input->post('action'). ' - '.$this->input->post('counselorcomments').'';
} else {
$comments = $this->input->post('action');
}
}
Also adding in a forms table (with the ID's and form names) allowed me to dynamically make the check boxes like so :
<?php
foreach ($elevennine as $form) { ?>
<label id="form"><input type="checkbox" name="form[]" value="<?php echo $form['form_id'] ?>" <?php echo set_checkbox('form', $form['form_id']) ?>><?php echo $form['forms'] ?></label>
<?php }
?>
Thanks for all the great ideas!
I'm working in PHP to build a form. I know how to display the form and then take submitted values from the $_POST variable, and I know how to validate those variables and display a "Thank You" or an "Error" page depending on the input.
What I don't know how to do, though, is create a client-side-like system wherein despite having my users hit a "back" button a separate screen I can then take the information I gathered from the first submission and display dynamic error messages like "Please provide a valid email address" or "First name is a required field" next to the fields that were entered incorrectly. I'd also like to retrieve any previously submitted data that was valid and have it populate in the form so users don't get frustrated by losing everything they entered.
What is the right approach to accomplishing something like this in PHP? I originally thought if I could pass back an array of error messages with an input type="hidden" tag I could then pull my values and display messages dynamically with PHP, but I keep getting stuck in that approach.
You could add the errors a php session, but this creates issues for users who have multiple browser tabs open.
My preferred method is to have the form submit to the same page and put the errors directly on that page so the user does not have to click the back button. That way you can highlight the fields directly in the form (make the background or outline red or something similar.)
<input type="text"
<?php (empty($_POST['field']?'style="backgroung-color: red;"':''))?>
name="field" value="<?php echo $_POST['field']?>" />
You can put <input type="text" name="field" value="<?php echo $_POST['field']?>" /> to get the old value.
Because the web is, by definition, stateless, there is no really good way to track what the user does when they hit the back button. There are hacks that work using a hidden iframe, but that is way more trouble that what you are looking for.
Don't mix client logic with server logic. The exact same script can output the form and take it's input. In case input successfully validates, it goes on. If not, it will display the form again, this time with error messages and the already-entered data.
Next time the user submits the form, validation starts again until it passes successfully.
So you extend the form with input values and error messages in the first place, but you only display them if flagged/set.
This can be done just with additional variables next to $_POST - or if you like it - by using a complete form abstraction from a framework, like zend framework (which might be overhead for what you like to do) or just with a library/component like the popular HTML_QuickForm2.
Edit:
This is some very bare code to demonstrate the overall methodology, if you use a library it is much nicer (and you don't have to code it instead you can concentrate on the actual form like the definition on top). This code is more for reading and understanding the flow than for using, I quickly typed it so it (most certainly has) syntax errors and it's not feature complete for a full blown form. This one has only one email field and is even missing the submit button:
/* setup the request */
$request->isSubmit = isset($_POST['submit']);
/* define the form */
$form->fields = array
(
'email' => array
(
'validate' => function($value) {return filter_var($value, FILTER_VALIDATE_EMAIL);},
'output' => function($value, $name) {return sprintf('<input type="text" value="%s" id="%s">', htmlspecialchars($value), htmlspecialchars($name)},
'default' => 'info#example.com',
),
);
/**
* Import form data from post request
*
* #return array data with keys as field names and values as the input strings
* or default form values.
*/
function get_form_post_data($form, $request)
{
$data = array();
foreach($form->fields as $name => $field)
{
$data[$name] = $field->default;
if ($request->isSubmit && isset($_POST[$name]))
{
$data[$name] = $_POST[$name];
}
}
return $data;
}
/**
* Validate form data
*/
function validate_form_data($form, $data)
{
foreach($form->fields as $name => $field)
{
$value = $data[$name];
$valid = $field['validate']($value);
if (!$valid)
{
$form->errors[$name] = true;
}
}
}
function display_form($form, $data)
{
foreach($form->fields as $name => $field)
{
$value = isset($data[$name]) ? $data[$name] : '';
$hasError = isset($form->errors[$name]);
$input = $field['output']($name, $value);
$mask = '%s';
if ($hasError)
{
$mask = '<div class="error"><div class="message">Please Check:</div>%s</div>';
}
printf($mask, $input);
}
}
// give it a run:
# populate form with default values -or- with submitted values:
$form->data = get_form_post_data($form, $request);
# validate form if there is actually a submit:
if ($request->isSubmit)
{
validate_form_data($form, $form->data);
}
# finally display the form (that can be within your HTML/template part), works like echo:
display_form($form, $form->data)
Use the form to submit to the same page, and if the form validates, use a header to redirect the user into the thank you page.
header("Location: thank-you.php");
If the form fails validation, you could easily display all the errors on the same page.
I am new to PHP and I was hoping someone could help me determine what the best way to go about creating a reusable view would be. What I have is a form that will be used to Add or Edit data. Therefore the view will be identical except in the case of an Edit the form fields will be populated.
So I am creating an HTML helper that takes 2 parameters. The first will be form data (if there is any{edit}) and the second will be a bool that flags whether this is an insert or and edit(to change form action).
My question is... how should I handle the first parameter if the form is to used to Add data and therefore does not contain data? Optional parameter?
EDIT--
I am using CodeIgnitor as my MVC framework. That is what those form functions are being inherited.. fyi
Thanks..
<?php
if(!defined('BASEPATH') ) exit('No direct script access allowed');
if(!function_exists('WorkOrderForm'))
{
function WorkOrderForm($array = array('$query'),$edit)
{
$formHtml = "";
$attributes = array('class'=>'order','id'=>'orderForm');
if($edit)
{
$formHtml += form_open('order/update',$attributes);
}
else
{
$formHtml += form_open('order/add',$attributes);
}
$formHtml += form_input('name',$query[0]->name);
$formHtml += form_textarea('name',$query[0]->description);
$dropOptions = array('nstarted'=>'Not Started','complete'=>'Done','started'=>'In Progress');
$formHtml += form_dropdown('status',$dropOptions,$query[0]->status);
$formHtml += form_input('name',$query[0]->startDate);
$formHtml += form_input('name',$query[0]->endDate);
$formHtml += form_close();
return $formHtml;
}
}
?>
What are you guys doing? A reusable view is so much easier than this. Simply create a view and save it in the views folder. Add the fields that will appear both when adding and editing data and use an if statement in the value parameter to determine if it has data.
E.g.
Controller:
public function add()
{
$data['method'] = 'add';
$data['form_data'] = $this->some_model->get_something();
$this->load->view('reusable_view', $data);
}
public function edit($id)
{
$data['method'] = 'edit';
$data['form_data'] = $this->some_model->get_something($id);
$this->load->view('reusable_view', $data);
}
View:
<form method="post" action="my_controller/" . <?php echo $method; ?>>
<input type="text" value="<?php if ( isset($form_data['something']) ) {echo $form_data['something'];} " />
</form>
I see no reason to populate a form in a controller as that's not the way MVC works. Using a helper in order to populate the form is also weird, I think you've slightly missed the point of how Codeigniter works.
First off, the default argument should be on the right. And I would default it to 'false' or NULL.
function WorkOrderForm($edit, $array = false)
Then maybe check if $array is not true, and set all the $query[0] to NULL? So something like...
if(!$array) {
$query[0]->name = $query[0]->description = $query[0]->status = null;
}
There might be a more direct approach, but that's one way.
Firstly, if you're sending your query to the helper function as an array, there is no reason to turn it into another array. ie $array = array('$query') should just be $query this way you can access properties like this: $query->name as opposed to $query[0]->name. Secondly, if you're not editing the form entry, your $query would be empty, so you can use that as the trigger for what to return (either the blank form or the populated form):
function WorkOrderForm($query)
{
if($query!='')
{
//$formHTML=populated form
} else {
//$formHTML=empty form
}
return $formHTML;
}
Okay? But, there's a problem... The code you have in your helper won't work. You're using an arithmetic operator += to (assuming) concatenate the form data. What this does is try to add 1 to a string, which will always equal 0. What you're looking for is the .= operator; this will concatenate the form as would be expected. However, this offers you little control over how the form will look (as is, it will put all the form elements side-by-side -- not too pretty). What you could do is instead of concatenating them all together, push them into an array, then echo the form elements out one-by-one:
if($query!=''){
$form_array=array();
array_push($form_array,form_open('order/update',$attributes));
array_push($form_array,form_input('name',$query->name));
array_push($form_array,form_textarea('name',$query->description));
$dropOptions = array('nstarted'=>'Not Started','complete'=>'Done','started'=>'In Progress');
array_push($form_array,form_dropdown('status',$dropOptions,$query->status));
array_push($form_array,form_input('name',$query->startDate));
array_push($form_array,form_input('name',$query->endDate));
array_push($form_array,form_close());
}else{
$form_array=array();
array_push($form_array,form_open('order/add',$attributes));
array_push($form_array,form_open('order/update'));
array_push($form_array,form_input('name'));
array_push($form_array,form_textarea('name'));
$dropOptions = array('nstarted'=>'Not Started','complete'=>'Done','started'=>'In Progress');
array_push($form_array,form_dropdown('status',$dropOptions));
array_push($form_array,form_input('name'));
array_push($form_array,form_input('name'));
array_push($form_array,form_close());
}
return $form_array;
Then to present the form elements, iterate through the $form_array array that was returned:
$form_data='';//blank for new item, or data to populate form with to edit an item
$form_el = WorkOrderForm($form_data);
foreach($form_el as $key=>$val){
echo $val.'<br>';//I just added a <br> here so each form element will be on a new line; change to fit your needs
}
Hope this helps...